2014-09-03 162 views
0

我有兩個型號,TrackPair。每個Pair具有track1,track2popularity。我試圖通過對的流行度(降序)得到一個有序列表,沒有兩個對具有相同的track1。以下是我試過到目前爲止:Django:不同的外鍵,然後訂購

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

您可能必須使用raw。 – okaram 2014-09-03 15:21:23

回答

2

首先,我們來澄清一下:DISTINCT是標準SQL,而DISTINCT ON是PostgreSQL擴展。

錯誤(DISTINCT ON expressions must match initial ORDER BY expressions)表示,你應該解決您的ORDER BY條款,而不是DISTINT ON(如果你這樣做,你最終會產生不同的結果,就像你已經經歷)。

The DISTINCT ON expression(s) must match the leftmost ORDER BY expression(s). The ORDER BY clause will normally contain additional expression(s) that determine the desired precedence of rows within each DISTINCT ON group.

這會給您的預計業績:

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 
+0

謝謝,這清除了。我最終遍歷了結果列表並刪除了重複項(在我的情況下,結果列表是否比請求更短並不重要),但是很好解釋這個用例。我不會認爲這樣的事情會如此模糊,以至於你的回答不在其他任何地方! – benwad 2014-09-04 11:06:34

1

documentation on distinct

第一:

On PostgreSQL only, you can pass positional arguments (*fields) in order to specify the names of fields to which the DISTINCT should apply.

你不」規定什麼是你的數據庫後端,如果它不PostrgreSQL你就沒有機會,使其工作。

二:

When you specify field names, you must provide an order_by() in the QuerySet, and the fields in order_by() must start with the fields in distinct(), in the same order.

我認爲你應該使用原始(),或獲得人氣有序對整個列表,然後通過做在TRACK1 Python的獨特的過濾。