2016-11-09 46 views
1

我想查詢一個表併爲該月的最後一天的所有行求和。Postgres - 從月份的最後一天開始總結行的快速方法

讓我們用以下表爲例:

CREATE TABLE example(dt date, value int) 

(真正的表具有更多的列,是比較大的,而真正的查詢是更復雜)

我有以下查詢:

SELECT dt, SUM(value) 
FROM example 
WHERE dt IN (SELECT DISTINCT 
    date_trunc('MONTH', generate_series('2012-01-01'::date, 
             '2016-12-01'::date, 
             interval '1 day') + INTERVAL '1 MONTH - 1 day')::date) 
GROUP BY dt 

它在我的真實表上運行約2秒鐘。

但是,如果我生成的結束一個月天的完整列表在我的範圍和參數化查詢,像這樣:

SELECT dt, SUM(value) 
FROM example 
WHERE dt IN ('2012-01-31', ...) 
GROUP BY dt 

這是更快,〜750毫秒。

我不希望生成日期並將它們傳遞給查詢,有沒有一種方法可以完全在SQL中完成此操作,並使其與後一版本一樣快?

回答

0

子選擇是不必要的複雜。它可以簡化爲:

SELECT dt, SUM(value) 
FROM example 
WHERE dt IN (SELECT d::date 
      from generate_series('2012-01-01'::date, '2016-12-01'::date, interval '1 month') dates (d) 
GROUP BY dt; --<< the group by is necessary 

也許這會加快查詢速度。

您也可以嘗試把日期代入CTE:

with dates (d) as (
    SELECT t::date 
    from generate_series('2012-01-01'::date, '2016-12-01'::date, interval '1 month') t 
) 
SELECT dt, SUM(value) 
FROM example 
WHERE dt IN (select d from dates) 
GROUP BY dt; 

有時候做一個連接也更高效:

with dates (d) as (
    SELECT t::date 
    from generate_series('2012-01-01'::date, '2016-12-01'::date, interval '1 month') t 
) 
SELECT dt, SUM(value) 
FROM example 
    JOIN dates on example.dt = dates.d 
GROUP BY dt; 
+0

下面是我實際使用的查詢:WHERE DT中(選擇date_trunc( '月''選擇DT,SUM(值) FROM例如 ,d)來自generate_series('2012-01-01':: date,'2016-11-10':: date,interval'1 month')日期(d))的間隔'1個月 - 1天' ' –

0

在您的查詢的性能問題來自事實你正在生成一個每日系列。將其更改爲每月除去distinct並添加group by

select dt, sum(value) 
from 
    example 
    inner join (
     select date_trunc('month', dt) + interval '1 month - 1 day' as dt 
     from generate_series('2012-01-01'::date, '2016-12-01', '1 month') gs (dt) 
    ) d using (dt) 
group by dt 
相關問題