我想查询一个表,并为该月最后一天的所有行汇总一列。
让我们使用下表作为示例:
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 :(得分: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;
答案 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