首頁  >  文章  >  後端開發  >  django orm中利用annotate進行group by

django orm中利用annotate進行group by

高洛峰
高洛峰原創
2016-11-23 09:43:043418瀏覽

用法

之前的orm的group by方法在django 1.8 中已經不能使用,需要利用annotate來實作

範例1

第一個values用來選取需要用來group by的欄位(此處group by by user_id ),之後再跟著annotate來分組並聚合需要的欄位(需要每個user_id對應的question_id的數量和catalog_id的最小值),之後再values來實際查詢需要的欄位(原user_id和聚合後的欄位的別名)

第一個values用來指定用來group by的字段,裡面必須是Count、Min等等聚合函數(例如用F("user_id")取別名是不行的),不需要最終查詢的就不必聚合了

第二個values用來指定實際select的字段,只能指定annotate後的字段名(以此處為例:user_id是用來分組的字段,可以直接取,而其他字段必須聚合並使用聚合後的別名,qid和cid,假如原表還有個字段status,annotate中沒有聚合此字段,所以最後value不能查詢該字段)

q = PxbNCEUserQuest.objects.filter(user_id=335).values("user_id").annotate(qid=Min("question_id"), cid=Min("catalog_id")).values("user_id", "qid", "cid")
print q
print q.query

# 输出
[{'qid': 22, 'user_id': 335L, 'cid': 17}]

SELECT `pxb_nce_user_quest`.`user_id`, MIN(`pxb_nce_user_quest`.`question_id`) AS `qid`, MIN(`pxb_nce_user_quest`.`catalog_id`) AS `cid` FROM `pxb_nce_user_quest` WHERE `pxb_nce_user_quest`.`user_id` = 335 GROUP BY `pxb_nce_user_quest`.`user_id` ORDER BY NULL

示例2

與示例1一樣,但是此處第一個annotate用來分組字段,第二個annotate用來單獨別名其他字段

q = PxbNCEUserQuest.objects.filter(user_id=335).values("user_id").annotate(qid=Min("question_id"), cid=Min("catalog_id")).annotate(uid=F("user_id")).values("uid", "qid", "cid")
print q
print q.query
# 输出:
[{'qid': 22, 'uid': 335L, 'cid': 17}]

SELECT MIN(`pxb_nce_user_quest`.`question_id`) AS `qid`, MIN(`pxb_nce_user_quest`.`catalog_id`) AS `cid`, `pxb_nce_user_quest`.`user_id` AS `uid` FROM `pxb_nce_user_quest` WHERE `pxb_nce_user_quest`.`user_id` = 335 GROUP BY `pxb_nce_user_quest`.`user_id` ORDER BY NULL

舉例:

SomeModel.objects.annotate(Count('somecol'))

GROUP BY: 所有字段

. ('name').annotate(Count('somecol'))

GROUP BY: name字段,聚合somecol

SomeModel.objects.annotate(Count('somecol')).values('name')

GRO

GRO BY: 所有字段,查詢name

SomeModel.objects.values('name', 'pk').annotate(Count('somecol')).values('pk')

GROUP BY: name, pk字段,查詢pk欄位

SomeModel.objects.values('name').annotate(Count('somecol')).values('pk')

GROUP BY: name, pk字段,查詢pk字段關聯知識

GROUP BY: name, pk字段,查詢pk字段關聯知識

剛開始上面的查詢方法可能比較難理,但是對比原生sql語句的group by方法就會發現類似原理

老版本mysql中

select a, b from t group by a會正常工作,b字段會自動取第一條,等於是隱式聚合了

新版本mysql中以上語句不能工作,因為預設啟用嚴格模式sql_mode=ONLY_FULL_GROUP_BY,正確方法是:

select a,max(b) as b from t group by,即需要顯示的聚合所有查詢的欄位


對比新版mysql語法會發現跟orm中查詢方法很類似

🎜🎜🎜
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn