带有注释的Django queryset,为什么GROUP BY应用于所有字段?

Fla*_*ing 8 python sql django postgresql orm

我正在使用带有PostgreSQL的Django 1.6,并有以下型号:

# models.py
class Game(AbstractContentModel, AbstractScoreModel):
    name = models.CharField(_("name"), max_length=100, blank=True)
    developer = models.CharField(_('Developer'), max_length=255)
    distributor = models.CharField(_('Distributor'), max_length=255, blank=True)
    # ...
    reviews = models.ManyToManyField(Review, related_name="games", blank=True, verbose_name=_("Reviews"))
    videos = models.ManyToManyField(Video, related_name="games", blank=True, verbose_name=_("Videos"))
    images = models.ManyToManyField(Image, related_name="games", blank=True, verbose_name=_("Gallery"))
Run Code Online (Sandbox Code Playgroud)

我正在尝试获取所有游戏,并且每个游戏都会添加相关视频,评论和图像,如下所示:

# views.py
qs = Game.objects.all()
qs = qs.annotate(video_count=models.Count('videos'))
qs = qs.annotate(review_count=models.Count('reviews'))
qs = qs.annotate(image_count=models.Count('images'))
Run Code Online (Sandbox Code Playgroud)

结果查询是:

SELECT 
"content_game"."id", 
"content_game"."name",
"content_game"."developer", 
"content_game"."distributor",
COUNT("content_game_videos"."video_id") AS "video_count",
COUNT("content_game_reviews"."review_id") AS "review_count", 
COUNT("content_game_images"."image_id") AS "image_count" 
FROM "content_game" 
LEFT OUTER JOIN "content_game_videos" ON ( "content_game"."id" = "content_game_videos"."game_id" )
LEFT OUTER JOIN "content_game_reviews" ON ( "content_game"."id" = "content_game_reviews"."game_id" ) 
LEFT OUTER JOIN "content_game_images" ON ( "content_game"."id" = "content_game_images"."game_id" ) 
GROUP BY 
"content_game"."id", 
"content_game"."name",
"content_game"."developer", 
"content_game"."distributor";
Run Code Online (Sandbox Code Playgroud)

我的问题是 - 为什么GROUP BY子句中有所有选定的字段?最重要的是,除了原始SQL之外,我怎么能摆脱它们呢?

我知道使用它会很好.values(),但我希望结果查询中的每个字段.如果我只是使用GROUP BY "content_game"."id",结果是一样的,但我不知道如何使用它与Django ORM一样.

Anu*_*dav 2

我来不及回答,但我已经研究过答案了。首先,OP所说的行为是正确的。它应该适用于所有类型的关系数据库,但正如 @lad2025 在评论中所说,唯一的 MySQL(以及 MariaDB)可以原谅这种行为。因此,我们必须学习它,而不是摆脱它。因为这是使用它/理解它并习惯它的唯一正确方法。

目前OP已经找到了解决方案,该解决方案是不断更新表字段的行数并稍后填充,而不是通过查询动态检索数据。

因为在使用聚合函数时,添加到 GROUP BY 中的任何内容都必须包含在 SELECT 中,反之亦然。

"content_game"."id", "content_game"."name", "content_game"."developer",  "content_game"."distributor"
Run Code Online (Sandbox Code Playgroud)

上述字段必须进入 GROUP BY,因为如果我尝试打印 id 或选择中的任何字段,则应返回哪一行的字段(单个)值?组中的最后一行或第一行是不正确的(MySQL 就是这样做的)。所以最好将所有内容都放入 GROUP BY 中。

为什么?由于不明确 -group by为每组记录生成一条记录。Group By列对于组中的所有记录包含相同的值,并且任何聚合函数都会为组生成单个值,但对于组 "content_game"."developer"可以不同,对于所有行来说也可以不同,因为它是主键。所有领域都一样。"content_game"."distributor""content_game"."id"

可以在这里找到很好的解释

我希望人们以更好的方式分享(编辑我的帖子)更多的声明。这样其他人将来就会发现这很有用。