问题描述
我想在第30天的行中计算前29天的总和,我使用过滤器和窗口函数,但是FILTER
不起作用,
如果我使用它,它仍然从头到尾求和:
Select *,Sum(quantity) filter (where time between time - interval '29 day' and time) over ()
from t1
如果我使用它,则显示空列
Select *,Sum(quantity) filter (where time between time - interval '29 day' and time - interval '1 day') over ()
from t1
数据,为简单起见,我减少了列数
Time sum_quantity
2020-01-01 1
2020-01-02 2
2020-01-03 3
2020-01-04 6
....
2020-01-30 100
数据类型:时间是日期,数量是整数
所需结果: 应该与第一个表格具有相同的列,并添加此移动总和列
第30天=每30天第1天到第29天的总量
如何解决此问题
解决方法
您希望使用带有range
的窗框定义的窗函数:
select t1.*,sum(quantity) over (order by time
range between interval '29 day' preceding and current row
)
from t1 ;
编辑:
如果您拥有所有日期的数据,则可以使用rows
:
select t1.*,sum(quantity) over (order by time
rows between 29 preceding and current row
)
from t1 ;
编辑II:
如果您需要在不支持range
的较旧版本的Postgres中处理丢失的日子,那么扩展数据可能是最简单的方法:
select t1.*,sum(quantity) over (order by time
rows between 29 preceding and current row
)
from (select generate_series(min(t1.time),max(t1.time),interval '1 day') as dte
from t1
) d left join
t1
on d.dte = t1.time;
您可能要过滤掉其他行:
select t1.*
from (select t1.*,sum(quantity) over (order by time
rows between 29 preceding and current row
) as running_sum
from (select generate_series(min(t1.time),interval '1 day') as dte
from t1
) d left join
t1
on d.dte = t1.time
) t1
where t1.time is not null;
,
您的filter (where)
子句始终为true,空over()
子句在所有结果集中都是窗口显示的。
您应该在over
子句中指定窗口,而不是在filter
子句中指定窗口。可能您需要类似
sum(quantity) over (order by time rows between 29 preceding and current row)
或更好的range between...
。
这是您想要的吗?
select m1.Time,(select sum(sum_quantity)
from mytable m
where m.time between (m1.time - interval '29 day') and (m1.time)) sum_total
from mytable m1
group by m1.Time
order by m1.Time;
或者也许更好:
select m1.Time,sum(m.sum_quantity)
from mytable m
join mytable m1 on m.time between (m1.time - interval '29 day') and (m1.time)
group by m1.Time
order by m1.Time;
这是一个演示:
,
请在易用的地方使用条件,因为您使用的是Windows函数,因此就像条件表达式一样:
SUM(<expression>) FILTER(WHERE <condition>)
SUM(CASE WHEN <condition> THEN <expression> END)