2013-01-11 69 views
5

用戶唯一我有一個Postgres的表看起來像這樣:SQL總和,每

id | user_id | state | created_at 

狀態可以是下列任何一種:

new, paying, paid, completing, complete, payment_failed, completion_failed 

我需要一個返回與下面的報告語句:按日期

  1. 款項支付所有國家的
  2. 按日期之所有已完成的狀態
  3. 和所有新的,支付,完成日期的狀態只有一個每用戶每天要算
  4. 總和的所有payment_failed,按日期completion_failed與每個用戶每天只有一個要算

到目前爲止,我有這樣的:

SELECT 
    DATE(created_at) AS date, 
    SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete, 
    SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid 
FROM orders 
WHERE created_at BETWEEN ? AND ? 
GROUP BY DATE(created_at) 

的進展和失敗國家的總和爲加入這選擇很容易:

SUM(CASE WHEN state IN('new','paying','completing') THEN 1 ELSE 0 END) AS in_progress, 
SUM(CASE WHEN state IN('payment_failed','completion_failed') THEN 1 ELSE 0 END) AS failed 

但我無法弄清楚如何每天只有一個user_id in_progress和失敗的狀態進行計數。

我需要這個的原因是在我們的統計數據中操縱失敗率,因爲許多觸發失敗或不完整訂單的用戶繼續觸發更多事件,從而導致我們的失敗率上升。

感謝您提前。

+0

你的PostgreSQL的版本? –

+0

@IgorRomanchenko 9.1.6 –

回答

2

試着這麼做:

SELECT 
    DATE(created_at) AS date, 
    SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete, 
    SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid, 
    COUNT(DISTINCT CASE WHEN state IN('new','paying','completing') THEN user_id ELSE NULL END) AS in_progress, 
    COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed') THEN user_id ELSE NULL END) AS failed 
FROM orders 
WHERE created_at BETWEEN ? AND ? 
GROUP BY DATE(created_at); 

主要思想 - COUNT (DISTINCT ...)將依靠獨特user_id並不會算NULL值。

詳情:aggregate functions4.2.7. Aggregate Expressions

具有相同的風格計數整個查詢和簡化CASE WHEN ...

SELECT 
    DATE(created_at) AS date, 
    COUNT(CASE WHEN state = 'complete' THEN 1 END) AS complete, 
    COUNT(CASE WHEN state = 'paid' THEN 1 END) AS paid, 
    COUNT(DISTINCT CASE WHEN state IN('new','paying','completing') THEN user_id END) AS in_progress, 
    COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed') THEN user_id END) AS failed 
FROM orders 
WHERE created_at BETWEEN ? AND ? 
GROUP BY DATE(created_at); 
+0

哇,這幾乎完美同步。 –

+0

@ErwinBrandstetter是的。查詢幾乎完全相同。 :) –

+0

如果可以的話,我也會接受你的回答,但是看起來Erwin會在幾分鐘內打敗你。謝謝你的幫助。 –

3
SELECT created_at::date AS the_date 
     ,SUM(CASE WHEN state = 'complete' THEN 1 ELSE 0 END) AS complete 
     ,SUM(CASE WHEN state = 'paid' THEN 1 ELSE 0 END) AS paid 
     ,COUNT(DISTINCT CASE WHEN state IN('new','paying','completing') 
         THEN user_id ELSE NULL END) AS in_progress 
     ,COUNT(DISTINCT CASE WHEN state IN('payment_failed','completion_failed') 
         THEN user_id ELSE NULL END) AS failed 
FROM orders 
WHERE created_at BETWEEN ? AND ? 
GROUP BY created_at::date 

我用the_date作爲別名,因爲它是不明智的(同時允許)使用關鍵詞日期作爲標識符。

你可以使用completepaid類似的技術,一個是作爲其他有好:

COUNT(CASE WHEN state = 'complete' THEN 1 ELSE NULL END) AS complete 
+0

我的天啊,快!非常感謝! –