2013-07-18 71 views
1

我有一個訂單表,其中的每一行都有一個名爲price的列。每個訂單還有一個名爲created_at的專欄,該專欄將說明訂單何時創建。獲取訂單號,使訂單總數爲1000

什麼是一個很好的方法來找出哪些訂單使總價格超過1000美元?

所以,假設我有一個看起來像這樣三個命令:

Order 1: price: $800 - created_at: 2013/07/11 

Order 2: price: $100 - created_at: 2013/07/13 

Order 3: price: $300 - created_at: 2013/07/14 

我有興趣在尋找3階是,使我度過超過$ 1000,因爲如果我們增加$ 800+ $ 100一個+ 300美元,恰恰是300美元,使總金額超過1000美元。

我可以執行什麼查詢來查找?

+0

什麼區別訂單?或者,會有多個結果,還是隻有一個? –

+0

主鍵是一個名爲uuid的列,它是一個唯一的字符串。 –

回答

0

計算與窗口集合函數sum()運行總和後,只需根據created_at超過1000接的第一行:

SELECT * 
FROM (
    SELECT order_id, created_at 
     , sum(price) OVER (ORDER BY created_at) AS sum_price 
    FROM orders 
    ) sub 
WHERE sum_price >= 1000 
ORDER BY created_at 
LIMIT 1; 

這應該比@Gordon's version更快,因爲採摘根據第一相同的已經在窗口函數中使用的順序比計算每行的值要便宜很多,這不是sargable

我使用sum_price >= 1000,所以達到1000也完全符合要求。如果只有超過應符合使用>而不是>=

The manual on window functions informs:

除了這些功能,任何內建或用戶定義的聚合 函數可以被用作一個窗函數

應當注意,這個查詢總是隻提供一行,而不是@戈登的查詢。如果有多行created_at跨越1000個障礙,所有這些行將符合Gordon的答案(否則將失敗,請參閱下文),而在我的領域中只有one。這將是一個任意的,只要你不添加更多的項目ORDER BY作爲tiebreaker。像:

ORDER BY created_at, order_id 

有ORDER的兩個實例通過這個查詢,它只是碰巧,你可以修改的一個或兩個,使其工作。爲了使排序順序一致,這應該是最快的。

其實,戈登的版本將完全失敗本次測試的情況:

CREATE TEMP TABLE orders(order_id int, price int, created_at date); 

INSERT INTO orders VALUES 
    (1, 500, '2013-07-01') 
,(2, 400, '2013-07-02') 
,(3, 100, '2013-07-03') 
,(4, 100, '2013-07-03') 
,(5, 100, '2013-07-03'); 

您可以通過窗口函數使排序順序解決它獨特的像上面這樣證實。

或者你可以改變幀定義爲窗口功能:

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 

Read the fine print in the manual.

但它是慢兩種方式。

-> SQLfiddle

0

對於這一點,你需要一個累積的總和,其Postgres提供作爲窗口函數:

select o.* 
from (select o.*, 
      sum(o2.price) over (order by created_at) as cumsum 
     from orders o 
    ) o 
where 1000 > cumsum - price and 1000 <= cumsum; 

where條款只是罰款,其中添加的價格首次超過$ 1000的行。

+0

嗨戈登,什麼是o2?我猜是從訂單o2的內部。 –

+0

@HommerSmith:'o2'只是一個錯字。你可以在這裏刪除*所有*表資格和表別名。但是,對於重複的'created_at',此查詢可能會完全失敗。我在我的回答中添加了一段。 –