我有两个模型,Track
和Pair
。每个Pair
都有track1
,track2
和popularity
。我试图通过对的流行度(降序)得到一个有序列表,没有两对具有相同的track1
。这是我到目前为止所尝试的内容:
lstPairs = Pair.objects.order_by('-popularity','track1__id').distinct('track1__id')[:iNumPairs].values_list('track1__id', 'track2__id', 'popularity')
这给了我以下错误:
ProgrammingError: SELECT DISTINCT ON expressions must match initial ORDER BY expressions
...所以我试过了:
lstPairs = Pair.objects.order_by('-popularity','track1__id').distinct('popularity', 'track1__id')[:iNumPairs].values_list('track1__id', 'track2__id', 'popularity')
这给了我重复track1__id
s的条目。有谁知道解决这个问题的方法?我猜我将不得不使用raw()
或类似的东西,但我不知道我是如何解决这样的问题的。我正在使用PostgreSQL作为数据库后端,因此应支持DISTINCT
。
答案 0 :(得分:3)
首先,让我们澄清一下:DISTINCT
是标准SQL,而DISTINCT ON
是PostgreSQL扩展。
错误(DISTINCT ON expressions must match initial ORDER BY expressions
)表示您应该修复ORDER BY
条款,而不是DISTINT ON
(如果您这样做,您最终会得到不同的结果,就像您一样已经经历过。)
DISTINCT ON
表达式必须与最左边的ORDER BY表达式匹配。 ORDER BY子句通常包含其他表达式,用于确定每个DISTINCT ON组中行的所需优先级。
这将为您提供预期的结果:
lstPairs = Pair.objects.order_by('track1__id','-popularity').distinct('track1__id')[:iNumPairs].values_list('track1__id', 'track2__id', 'popularity')
在SQL中:
SELECT DISTINCT ON (track1__id) track1__id, track2__id, popularity
FROM pairs
ORDER BY track1__id, popularity DESC
但可能的顺序错误。
如果您需要原始订单,可以在此处使用子查询:
SELECT *
FROM (
SELECT DISTINCT ON (track1__id) track1__id, track2__id, popularity
FROM pairs
ORDER BY track1__id
-- LIMIT here, if necessary
)
ORDER BY popularity DESC, track1__id
答案 1 :(得分:1)
首先:
你没有'指定你的数据库后端是什么,如果它不是PostrgreSQL,你就没有机会让它工作。仅在PostgreSQL上,您可以传递位置参数(* fields)以指定DISTINCT应应用的字段的名称。
第二
指定字段名称时,必须在QuerySet中提供order_by(),order_by()中的字段必须以distinct()中的字段开头,顺序相同。
我认为你应该使用raw(),或者获得按流行度排序的整个Pairs列表,然后在Python中按track1唯一性进行过滤。