2011-08-21 47 views
4

我想是什麼力量讓一個表的統計信息,爲此我使用generate_series();Postgres的generate_series

下面是我在做什麼:

SELECT x.month, amount 
FROM (SELECT generate_series(
       min(date_trunc('month', date)), 
       max(date_trunc('month', date)), 
       '1 month' 
    ) AS month 
     FROM table 
     WHERE user_id = 55 AND ... 
) x 
LEFT JOIN (
     SELECT SUM(amount) AS amount, date_trunc('month', date) AS month 
     FROM table 
     WHERE user_id = 55 AND ... 
     GROUP BY month 
) q ON q.month = x.month 
ORDER BY month 

這種運作良好,但是當我想要應用過濾器,例如獲取特定用戶的金額,我必須將它們應用兩次。有沒有辦法避免過濾兩次,或以更有效的方式重寫,因爲我不確定這是否是正確的方法?

回答

9

你可以寫WITH query此:

WITH month_amount AS 
(
    SELECT 
     sum(amount) AS amount, 
     date_trunc('month', date) AS month 
    FROM Amount 
    WHERE user_id = 55 -- AND ... 
    GROUP BY month 
) 
SELECT month, amount 
FROM 
    (SELECT generate_series(min(month), max(month), '1 month') AS month 
    FROM month_amount) x 
LEFT JOIN month_amount 
USING (month) 
ORDER BY month; 

結果舉例:

SELECT * FROM amount WHERE user_id = 55; 
amount_id | user_id | amount | date  
-----------+---------+--------+------------ 
     3 |  55 |  7 | 2011-03-16 
     4 |  55 |  5 | 2011-03-22 
     5 |  55 |  2 | 2011-05-07 
     6 |  55 |  18 | 2011-05-27 
     7 |  55 |  4 | 2011-06-14 
(5 rows) 

WITH month_amount .. 
     month   | amount 
------------------------+-------- 
2011-03-01 00:00:00+01 |  12 
2011-04-01 00:00:00+02 |  
2011-05-01 00:00:00+02 |  20 
2011-06-01 00:00:00+02 |  4 
(4 rows) 
+0

我從來沒有想過CTE,但他們真的很有用。非常感謝,它非常完美。 – yokoloko

+0

+1我學到了一些我對postgres不瞭解的東西 - 謝謝:) – Bohemian

+0

如何生成如 這樣的系列從generate_series(01,12)中選擇m輸出:01,02,03,04,05,06,07 ,08,09,10,11,12 –

6

你可以子句中的執行您的查詢,然後使用SELECT添加缺少的月份:

WITH query AS (
     SELECT SUM(amount) AS amount, date_trunc('month', date) AS month 
     FROM table 
     WHERE user_id = 55 AND ... 
     GROUP BY month 
) 
SELECT date(d.month) AS month, q.amount 
FROM (
    SELECT generate_series(min(month), max(month), '1 month') AS month 
    FROM query 
    ) d 
    LEFT JOIN query q ON q.month = d.month 
ORDER BY month