sqlalchemy的關聯子查詢
阿新 • • 發佈:2019-01-22
SQLAlchemy也算是用過好幾年了,不過一直都用著其中相對簡單的一小部分,最近寫個程式碰到個問題,需要作一個關聯子查詢,類似這樣的SQL語句:
SELECT master.*, (
SELECT count(*)
FROM detail
WHERE detail.parentid=master.id AND detail.someflag IS NOT NULL
) FROM master;
試了很久不知道怎麼用ORM來寫。
如果COUNT不為0,用下面這個查詢的結果是一樣的:
SELECT master.id, count(detail.id) FROM master INNER JOIN detail ON detail.parentid=master.id WHERE detail.someflag IS NOT NULL GROUP BY master.id;
這個語句倒是可以用ORM實現:
qry = orm.query(master, func.count(detail.id).join(detail,
detail.parentid==master.id).filter(detail.someflag!=None).group_by(master)
但是如果COUNT為0就不行了,即便用OUTER JOIN也不行,這種情況下會丟失COUNT為0的master記錄。
想來想去大概只能用子查詢實現,但是試了這樣的語句,結果跟上面一個是一樣的,也會丟失COUNT為0的master記錄。
subqry = orm.query(detail.parentid, func.count(detail.id).label( "flagcnt").filter(detail.someflag!=None).group_by(detail.parentid).subquery() qry = orm.query(master, subqry.c.flagcnt).join(subqry, subqry.c.parentid==master.id)
這句的SQL相當於這樣:
SELECT master.id, subqry.flagcnt
FROM master
JOIN (
SELECT detail.parentid, count(*) AS flagcnt
FROM detail
WHERE detail.someflag IS NOT NULL
GROUP BY detail.parentid
) AS subqry ON subqry.parentid=master.id
沒辦法,只好繼續搜尋,最後還是在SO上看到一個類似問題的答案而受到啟發,解決了這個困擾了一天多的問題。
subqry = orm.query(func.count(detail.id).label("flagcnt")).filter( detail.parentid==master.id).filter(detail.someflag!=None).correlate(master).as_scalar() qry = orm.query(master, subqry)
其中的重點就在於correlate和as_scalar。