2013-02-12 24 views
-1

我想在Postgres中運行一個按預期方式返回結果集的查詢(比如說SELECT * FROM products ORDER BY created_at DESC),但將結果稍微調整一下,這樣就不會有太多連續的結果共享supplier_id值。隨機化查詢結果共享某個屬性

這一點尤其重要,因爲每個供應商的產品往往大致同時進口,因此created_at一樣,這意味着幾頁結果往往只有1個供應商的產品。

你怎麼混在一起的?

+0

你是否希望每個供應商中只有一個出現在這個洗牌數據集中,或者重複供應商都可以,只要他們不是「太頻繁」? – 2013-02-12 15:05:52

+0

您是否縮進以**隨機**訂購 – frictionlesspulley 2013-02-12 15:06:31

+0

重複可以,但不會太頻繁。我只是不希望具有相同'supplier_id'的X產品連續出現。 – Avishai 2013-02-12 15:07:39

回答

1

如果我終於明白你的問題吧,window function row_number()應該做的工作,用正確的PARTITION

SELECT * 
FROM (
    SELECT *, row_number() OVER (PARTITION BY created_at, supplier_id 
           ORDER BY created_at DESC) AS rn 
    FROM products 
    ) a 
WHERE rn <= X 
ORDER BY created_at DESC 

OVER子句中的ORDER BY是可選的,但它在我和Postgres的測試,加快執行9.1,因爲它與最終的ORDER BY條款同步。

最多可以同時從同一供應商處選擇X行。如果您需要真正的隨機選擇,則必須在OVER子句中額外訂購random()

除此之外,這不是「隨機化」或「重新洗牌」,而是抑制多餘的行。如果要顯示這些行(超過X),則必須按排序順序定義位置。儘管如此,它將不可避免地破壞時間順序。

0

我的理解是要以時間順序排序結果,但對於created_at特定的值,只有一個supplier_id不同的價值,你會希望有一些相反,假設他們在也非常接近排序列表。直接作爲排序標準時

的關鍵問題將是的created_at分辨率,無論是它(timestamp具有亞秒級分辨率,timestamp(0)將有一秒的分辨率)太高。

您可以嘗試按照時間範圍進行排序。例如:

ORDER BY (extract(epoch from created_at)/3600)::int, RANDOM() 

會命令首先由小時(3600秒)插入的條目,如自1/1/70的經過的小時數來測量,然後洗牌內部這一範圍的結果與次級排序(隨機)。如果在同一個小時內插入不同供應商的可能性仍然很小,則需要幾個小時或幾天。