总结:
ordered_tags = tagged_items.annotate(freq=Count('tag_id')).order_by('-freq')
for i in ordered_tags:
print(i.tag_id, i.tag, i.freq)
这并不等同于GROUP BY tag_id ORDER BY COUNT(tag_id) DESC
。为什么?
使用Django ORM,我正在尝试这样做:
SELECT tag_id, COUNT(tag_id) AS freq
FROM taggit_taggeditem
WHERE content_type_id IN (
SELECT id FROM django_content_type
WHERE app_label = 'reviews'
AND model IN ('problem', 'review', 'comment')
) AND (
object_id = 1
OR object_id IN (
SELECT id FROM review
WHERE problem_id = 1
) OR object_id IN (
SELECT c.id FROM comment AS c
INNER JOIN review AS r
ON r.id = c.review_id
)
)
GROUP BY tag_id
ORDER BY freq DESC;
这就是我设计的:
querydict_for_content_type_id = {
'current_app_label_query' : Q(app_label=ReviewsConfig.name),
'model_name_query' : Q(model__in=['problem', 'review', 'comment'])
}
# used in content_type_query
query_for_content_type_id = reduce(operator.__and__, querydict_for_content_type_id.values())
# Query relevant content_type from TaggedItem model.
content_type_query = Q(content_type_id__in=ContentType.objects.filter(query_for_content_type_id))
# Query relevant object_id from TaggedItem model.
object_query = Q(object_id=pk) | Q(object_id__in=problem.review_set.all())
for review in problem.review_set.all():
object_query |= Q(object_id__in=review.comment_set.all())
tagged_items = TaggedItem.objects.filter(content_type_query&object_query)
# JOIN Tag
# tags = tagged_items.select_related('tag')
# GROUP BY freq ORDER_BY freq DESC;
ordered_tags = tagged_items.annotate(freq=Count('tag_id'))#.order_by('-freq')
for i in ordered_tags:
print(i.tag_id, i.tag, i.freq)
Django ORM无法正常工作。在ordered_tags上调用distinct
方法也不起作用。
输出:
18 tag1 1
19 tag2 1
20 tag3 1
...
18 tag1 1
为什么我得到两次18 tag1 1
而不是18 tag1 2
?
1条答案
按热度按时间nuypyhwy1#
.annotate()
完全不等于GROUP BY
。通常使用Django的ORM来翻译SQL查询不是一个好主意。它的目的是帮助你解决一个问题,把你的想法转化为查询。
将TaggedItem示例作为包含
GROUP BY
语句的SQL查询的结果不会有任何意义,因为这些示例不代表TaggedItem表的一行。要获得
GROUP BY
语句,需要通过强制结果为dict来摆脱模型层。