我有以下Django模型:
class myModel(models.Model):
name = models.CharField(max_length=255, unique=True)
score = models.FloatField()
此模型的数据库中有数千个值。我想高效优雅地使用QuerySets获得前十名最高分,并按分数的降序显示名称。到目前为止它相对容易。
皱纹在哪里:如果有多个myModel并列第十名,我想全部展示它们。我不想只看到其中一些。这会过度地使某些名字比其他名字具有任意优势。如果绝对必要,我可以在Querysets之外进行一些后DB列表处理。但是,我看到的主要问题是我无法通过apriori将我的数据库查询限制在前10个元素中,因为据我所知,可能有一百万条记录都排在第十位。
我是否需要按分数对所有myModel进行排序,然后对它们进行一次传递以计算得分阈值?然后将该计算得分阈值用作另一个Queryset中的过滤器?
如果我想用直接SQL写这个,我甚至可以在一个查询中做到这一点吗?
答案 0 :(得分:13)
当然,您可以在一个SQL查询中执行此操作。使用django ORM生成此查询也很容易实现。
top_scores = (myModel.objects
.order_by('-score')
.values_list('score', flat=True)
.distinct())
top_records = (myModel.objects
.order_by('-score')
.filter(score__in=top_scores[:10]))
这应生成单个SQL查询(带子查询)。
答案 1 :(得分:1)
作为替代方案,您也可以使用两个SQL查询来执行此操作,某些数据库可能比单个SQL查询方法更快(IN操作通常比比较更昂贵):
myModel.objects.filter(
score__gte=myModel.objects.order_by('-score')[9].score
)
同样,在执行此操作时,您应该在分数字段上有一个索引(特别是在谈论数百万条记录时):
class myModel(models.Model):
name = models.CharField(max_length=255, unique=True)
score = models.FloatField(db_index=True)
答案 2 :(得分:0)
作为@ KrzysztofSzularz答案的替代方案,您也可以使用原始SQL来执行此操作。
有两个SQL操作可以获得你想要的东西
SELECT score from my_application_mymodel order by score desc limit 10;
以上sql将返回前10个分数(limit
执行此操作)
SELECT name, score from my_application_mymodel where score in (***) order by score desc;
这将返回所有得分值在第一个查询结果中的结果。
SELECT name, score from my_application_mymodel where score in (SELECT score from my_application_mymodel order by score desc limit 10) order by score desc;
您可以使用Raw Queries,但在尝试运行时可能会收到错误消息。所以using custom queries是最好的
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT name, score from my_application_mymodel where score in (SELECT score from my_application_mymodel order by score desc limit 10) order by score desc;")
return cursor.fetchall()
这将返回一个列表:
[("somename", 100.9),
("someothername", 99.9)
...
]
Django根据您的django模型名称(全部小写)和模型所在的应用程序名称来命名表,并使用下划线将它们连接起来。与my_application_mymodel