2016-11-09 13 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秒で実行されます。

しかし、私は私の範囲内で月末の日の完全なリストを生成し、そのようなクエリをparameterise場合:

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

それははるかに速く、〜750msです。

日付を生成してそのようなクエリに渡すのは好きではありませんが、これを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; 

は時々JOINをやっても、より効率的である:

クエリでのパフォーマンス上の問題が事実から来て
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

は私が実際に使用したクエリだ追加+ interval '1 month - 1 day' generate_series( '2012-01-01' :: date、'2016-11-10 ':: date、interval' 1 month ')dates(d) –

0

あなたは毎日のシリーズを生成しています。 (中dtがdate_trunc( '月'、D)を選択するWHERE例 FROM `DTを選択、SUM(値) :毎月に変更し、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 
関連する問題