values(...).annotate(...) sinh GROUP BY theo đúng các cột liệt kê trong values() đứng trước annotate().
Thứ tự hai lời gọi quyết định ý nghĩa câu truy vấn:
# group by status: one row per status
Order.objects.values('status').annotate(total=Count('id'))
# annotate per row, then only pick two columns: no grouping
Order.objects.annotate(total=Count('item')).values('status', 'total')Vì sao order_by() phá nhóm: cột nào xuất hiện trong ORDER BY cũng buộc phải nằm trong GROUP BY (yêu cầu của SQL). Thêm .order_by('created_at') vào query gom nhóm ở trên là nhóm theo (status, created_at) — mỗi đơn hàng thành một nhóm riêng, total đâu đâu cũng bằng 1.
Cạm bẫy hơn nữa: nếu model có Meta.ordering, ordering đó được áp dụng ngầm và gây đúng lỗi trên mà không thấy dòng order_by nào trong code. Django 3.1 đã bỏ hành vi này, nhưng codebase cũ vẫn dính.
Quy tắc an toàn cho query gom nhóm:
(Order.objects
.order_by() # clear Meta.ordering first
.values('status')
.annotate(total=Count('id'))
.order_by('-total')) # order by the annotation onlyGọi .order_by() rỗng để xoá ordering mặc định, và chỉ sắp xếp theo chính cột annotate hoặc cột đã có trong values().
Khi nghi ngờ, print(qs.query) và soi mệnh đề GROUP BY.