2017-08-18 13 views
0

請幫助我構建PostgreSQL查詢。 有2個表:產品(編號,名稱)和價格(ID,PRODUCT_ID,價格類型,那一刻,值)使用JOIN構建SQL查詢並限制

時刻 - 時間戳,可以在過去或未來

假設價格類型只有兩個選項:零售購買

但是,一個產品可能有許多不同時刻的零售價格。

我需要選擇所有產品的實際零售和採購價格,其中時間比現在少。

這是我能做到

SELECT 
     products.id, 
     products.title_translations AS title, 
     retail_prices.moment AS ret_moment, 
     pur_prices.value AS purchase, 
     retail_prices.value AS retail 
FROM products 
LEFT OUTER JOIN prices AS pur_prices ON products.id=pur_prices.product_id AND pur_prices.price_type='purchase' AND pur_prices.moment<current_timestamp 
LEFT OUTER JOIN prices AS retail_prices ON products.id=retail_prices.product_id AND retail_prices.price_type='retail' AND retail_prices.moment<current_timestamp 
ORDER BY products.id; 

它的工作原理,但返回 產品符合所有的價格,但我只需要最後的價格(通過時刻)。

+0

你的意思是說,現在的價格更近了嗎? – scaisEdge

+0

所以零售和採購價格應該在同一行,但可能有不同的「時刻」是正確的? – xQbert

+0

是的,在結果時刻沒有問題 – greenif

回答

2

只需使用ROW_NUMBER找到什麼是當前的時間

with last_prices as (
    SELECT 
      products.id, 
      products.title_translations AS title, 
      prices.moment, 
      prices.value, 
      prices.price_type, 
      ROW_NUMBER() OVER (PARTITION BY product_id, price_type 
          ORDER BY moment DESC) as rn 
    FROM products 
    LEFT JOIN prices 
     ON products.id = prices.product_id 
    WHERE moment < now() 
) 
SELECT id, title, 
     MAX(CASE WHEN price_type = 'retail' 
       THEN moment 
      END) as retail_moment, 
     MAX(CASE WHEN price_type = 'retail' 
       THEN value 
      END) as retail_price, 
     MAX(CASE WHEN price_type = 'purchase' 
       THEN moment 
      END) as purchase_moment, 
     MAX(CASE WHEN price_type = 'purchase' 
       THEN value 
      END) as purchase_price 
FROM last_prices  
WHERE rn = 1 
GROUP BY id, title 
ORDER BY id 
+0

選擇仍顯示'retail_prices.xxxx',並且您不再擁有該表/別名 – xQbert

+0

不爭議。但select ... retail_prices.value會拋出語法錯誤,因爲您的連接中只有產品和pur_prices。我想你沒有加入任何東西。 – xQbert

+0

@xQbert固定。謝謝 –

0

你可能會想它降序排列對於時刻訂購前的最後價格。 變化 ORDER BY products.id;ORDER BY product.id ASC, moment DESC;

+0

除此之外,有涉及的類型字段。並且他們想要在同一行結果上進行回扣/購買。 – xQbert

2

爲了保持組織的,直在我的腦海,我會使用熱膨脹係數來生成價格數據的兩個子集,一個是購買一個零售和升序順序分配行號具有最近時刻小於當前時間的地圖的最低數字。然後,當我們加入這些ctes時,我們只返回分配的最低號碼。

With Pur_prices as (SELECT P.*, row_Number() over (partition by product_ID order by moment desc) RN 
        FROM prices P 
        WHERE price_Type = 'purchase' 
        and p.moment < current_timestamp) 

, Retail_prices as (SELECT P.*, row_Number() over (partition by product_ID order by moment desc) RN 
        FROM prices P 
        WHERE price_Type = 'retail' 
        and p.moment < current_timestamp) 

SELECT 
     p.id, 
     p.title_translations AS title, 
     rp.moment AS ret_moment, 
     rp.value AS retail, 
     pp.moment AS Pur_moment, 
     pp.value AS purchase 
FROM products p 
LEFT JOIN pur_prices pp 
    ON p.id=pp.product_id 
AND pp.RN = 1 --Only show the most recent price less than current time 
LEFT JOIN retail_prices rp 
    ON p.id=rp.product_id 
AND RP.RN = 1 --Only show the most recent price less than current time 
ORDER BY p.id; 

最終結果應該是所有產品,無論他們是否有零售或採購價格;但如果他們確實顯示了現在之前最近一刻的零售/採購定價。我唯一關心的是這意味着所有定價都有一個時刻開始(不允許空值)!

+0

非常感謝,兩種變種都是有效的! – greenif