【发布时间】:2015-10-12 10:25:25
【问题描述】:
我正在尝试根据在多场比赛中获得的积分为球队分配排名。积分多的队伍排名靠前,积分相同的队伍排名靠前。团队可以有相同的排名。
因为 Django(也不是 SQLite)支持 DENSE_RANK 窗口函数,我必须在 Python 中计算排名。虽然最初我对all() 返回的模型实例执行此操作,但我决定应该能够为annotate().order_by() 返回的QuerySet 添加排名,同时保留一个QuerySet 对象以供使用,例如get()。
class TeamManager(models.manager):
@staticmethod
def add_ranking(qs):
# First, populate rows and rankings lists
# ...
# Then, add it to the query set
literal_selects = []
for row_id, ranking in zip([row.id for row in rows], rankings):
literal_selects.append('SELECT {} AS "thing_id", {} AS ranking'.format(row_id, ranking))
extra_from = "(" + " UNION ALL ".join(literal_selects) + ")"
return qs.extra(
tables=[extra_from],
select={'ranking': 'ranking'},
where=['team.id = thing_id'])
def ranked_list(self):
qs = self.model.objects.annotate(
num_games=Count('team__score_set'),
total_points=Sum('team__score_set__points'),
# Ideally, I would calculate ranking here
).order_by('-total_points')
return TeamManager.add_ranking(qs)
这不起作用,因为 Django 的 ORM adds double quotes 在 extra(table) 中的“表名”周围
是否有任何其他方法可以将文字值添加到预先存在的 QuerySet,或者我必须用对 raw() 的调用替换对注释的调用,然后从那里开始工作?这将是一个遗憾,因为我刚刚投入了大量时间来了解如何将我的原始原始 SQL 查询(使用 GROUP BYs 和所有内容)转换为更 Djangoesque 的做事方式。我很想用 Django 摆脱这种情况,而不是跟着我自己的旧 SQL 曲调跳舞。
【问题讨论】:
-
不,我认为您将不得不使用
raw... 一个更“可行”的选项是将查询烘焙到一个视图中,该视图可以作为单独的模特来自django-postgres.readthedocs.org/en/latest/views.html -
不是一个实际的答案,但是当我在计算排名时遇到类似的问题时,我最终创建了另一个只包含“积分/分数”的表格。当我们遍历一些大表时,它也使查询速度更快。因此,也许有一种方法可以让您创建和使用某种“积分”表。
-
原谅我,但从我的角度来看似乎是排序问题,按total_points和-num_games排序,如果点数相同,则num_games最少的团队将首先(添加排序以 id 结尾,这样你就可以避免在同等级别和游戏中出现分页问题)
标签: python sql django django-models sqlite