Django等价于SQL语句?还有,与RawQuerySets合作?
我遇到了一个没有很好记录的难题,你需要同时分组和排序 编辑以包括一些模型:Django等价于SQL语句?还有,与RawQuerySets合作?,sql,django,Sql,Django,我遇到了一个没有很好记录的难题,你需要同时分组和排序 编辑以包括一些模型: class Matchup(models.Model): player = models.ForeignKey(Player) opponent = models.ForeignKey(Player) score = models.IntegerField() match = models.ForeignKey(Match) class Match(models.Model):
class Matchup(models.Model):
player = models.ForeignKey(Player)
opponent = models.ForeignKey(Player)
score = models.IntegerField()
match = models.ForeignKey(Match)
class Match(models.Model):
game = models.CharField()
我想我已经包括了所有重要的东西。我正在尝试制作一个排行榜,每个玩家只能有一个条目。因此,我需要按玩家分组,并按('-skill')排序。我在distinct()上乱搞了很长一段时间,没有得到好的结果
经过数小时的反复试验,我通过执行原始SQL找到了90%的解决方案:
SELECT * FROM (SELECT * FROM scores ORDER BY score DESC) AS temp_table GROUP BY user ORDER BY score DESC
诚然,我并不完全理解SQL(主要是,为什么第二个命令是必需的?)
1) 这是最好的方式吗?我无法使用Django ORM返回正确的结果集,但很可能我只是做得不好
2) 我想通过外键关系进一步过滤(match.game,希望每场比赛都有高分)。使用rawqueryset时的最佳方法?首先在旁注上:在您的示例中,不需要使用firstORDER BY
。它们从不在子选择中,事实上,对于较小的RDBMS,它会引入一个不必要的排序操作(我想大多数人会忽略这个orderby
)。(Edit:严格来说,这不是事实。但是,在大多数用法中,表的顺序并不重要,只有结果集的顺序才重要。您的查询实际上是一个有趣的例外)
但您所做的工作可以通过Django ORM完成,不需要原始SQL。一般来说,您的SQL有点奇怪。基本上,您可以将其改写为:
SELECT
*
FROM
scores
GROUP BY
user
ORDER BY
score DESC
subselect实际上没有做任何事情(排序对于源数据来说并不重要,只在输出中),所以它就消失了
因此,在本例中,对于Django ORM部分,您可以使用来完成所需的任务
编辑-由于您在评论中指出,由于在分组
时使用SELECT*
[1]而不进行任何聚合的副产品,第一个订购人实际上会产生某种效果,因此相关SQL为:
SELECT
user
,MAX(score) AS high_score
FROM
scores
GROUP BY
user
ORDER BY
MAX(score) DESC
同样,您可以使用上面链接中提到的聚合特性来获得等效的ORM语句。看起来是这样的:
User.objects.annotate(high_score=Max('scores__score')).order_by('high_score')
这假设您有一个从Score
到User
的外键(Django将研究如何将这两个外键结合起来,从您的Score
模型中获取相关字段Score
)
[1] -这也突出了为什么在实际代码中使用SELECT*
不是一个好的做法 你好!也许你可以先解释一下(甚至用一些样本数据)你到底想做什么?有时仅仅通过查看代码就很难猜到。是的,我很抱歉。我通常比较彻底。我编辑了一些模型。您的SQL只返回用户获得的第一个分数。小组只获得第一分。然后,分数按分数排序,这会导致错误的结果集(玩家可以获得很多分数,我只想要他们的最高分数(实际上是当前的,但我接受最高分数)。啊哈,那么你应该使用MAX()
。使用没有任何聚合函数(COUNT
,SUM
,MAX
,等等)的GROUP BY
)往往没有任何意义,这就是为什么我忽略了这一点。Django能在没有在模型中指定的情况下操纵高分吗?@sejje yeah,使用我指定的链接中的annotate
函数-我编辑了该函数,试图将其转换为ORM语法(未经测试),谢谢danny boy!读了这篇文章后,我会试一试。