Sql 与行上的滞后/超前合并?

Sql 与行上的滞后/超前合并?,sql,postgresql,Sql,Postgresql,嘿,伙计们,假设我有一个数据框 Year Month 1_month_sub 3_month_sub 12_month_sub 2014 1 3 1 1 2014 2 1 0 0 2014 3 1 0 0 2014

嘿,伙计们,假设我有一个数据框

    Year   Month   1_month_sub   3_month_sub   12_month_sub
    2014     1         3             1              1
    2014     2         1             0              0
    2014     3         1             0              0
    2014     4         1             0              0
    2014     5         4             0              0
    2014     6         1             0              0
    2014     7         5             0              0
    2014     8         1             0              0
    2014     9         1             0              0
    2014     10        6             0              0
    2014     11        1             0              0
    2014     12        3             0              0
其中1个月sub表示购买了1个月的订阅,3个月sub表示购买了3个月的订阅等。 我需要添加一个专栏,让我在任何给定的时间单位每月订阅一次。因此,结果如下所示:

    Year   Month   1_month_sub   3_month_sub   12_month_sub  subs
    2014     1         3             1              1         5
    2014     2         1             0              0         3
    2014     3         1             0              0         3
    2014     4         1             0              0         2
    2014     5         4             0              0         5
    2014     6         1             0              0         2
    2014     7         5             0              0         6
    2014     8         1             0              0         2
    2014     9         1             0              0         2
    2014     10        6             0              0         7
    2014     11        1             0              0         2
    2014     12        3             0              0         4
    2015      1        1             0              0         1

我使用了联合、滞后、超前功能,但没有取得真正的成功。有什么办法吗?

你试过类似的方法吗

编辑:@Gordon Linoff下面的答案更好-相同的想法,但将前3个和前12个值封装在单个表达式中

select subs=(1_month_sub) + 
            lag(3_month_sub, 2, 0) over (order by Year, Month) +
            lag(3_month_sub, 1, 0) over (order by Year, Month) + 
            3_month_sub + 
            lag(12_month_sub, 11, 0) over (order by Year, Month) + 
            lag(12_month_sub, 10, 0) over (order by Year, Month) + 
            lag(12_month_sub, 9, 0) over (order by Year, Month) + 
            lag(12_month_sub, 8, 0) over (order by Year, Month) + 
            lag(12_month_sub, 7, 0) over (order by Year, Month) + 
            lag(12_month_sub, 6, 0) over (order by Year, Month) + 
            lag(12_month_sub, 5, 0) over (order by Year, Month) + 
            lag(12_month_sub, 4, 0) over (order by Year, Month) + 
            lag(12_month_sub, 3, 0) over (order by Year, Month) + 
            lag(12_month_sub, 2, 0) over (order by Year, Month) + 
            lag(12_month_sub, 1, 0) over (order by Year, Month) + 
            12_month_sub
from MyTable

我推测数据在一个表格中,1个月的SUB只存在1个月,3个月的SUB存在3个月,12个月的SUB存在12个月

此外,我将假设每个月都有一个连续

您可以在Postgres中使用累积和上的窗口子句执行此操作:

select t.*,
       (1_month_sub +
        sum(3_month_sub) over (order by year rows between 2 preceding and current row) +
        sum(12_month_sub) over (order by year rows between 11 preceding and current row)
       ) as total_subs
from t;

没有电源功能也可以做到这一点。下面已经在PostgreSQL和MS SQL上进行了测试

请参见SQL FIDLE的工作原理:

简单SQL连接

select
t1.Year,
t1.Month,
    sum(case when ((t2.Year-2014)*12+t2.Month) <= ((t1.Year-2014)*12+t1.Month) and ((t2.Year-2014)*12+t2.Month) - ((t1.Year-2014)*12+t1.Month) > -1 then 1 else 0 end * t2.one_ms) +
    sum( case when ((t2.Year-2014)*12+t2.Month) <= ((t1.Year-2014)*12+t1.Month) and ((t2.Year-2014)*12+t2.Month) - ((t1.Year-2014)*12+t1.Month) > -3 then 1 else 0 end * t2.three_ms ) +
    sum( case when ((t2.Year-2014)*12+t2.Month) <= ((t1.Year-2014)*12+t1.Month) and ((t2.Year-2014)*12+t2.Month) - ((t1.Year-2014)*12+t1.Month) > -12 then 1 else 0 end * t2.twelve_ms ) as subs
from Test t1
    join Test t2
        on 1=1
group by t1.Year, t1.Month, ((t1.Year-2014)*12+t1.Month)
order by ((t1.Year-2014)*12+t1.Month)
工作:

为了更好地理解它,您可能需要为t1.Year-2014*12+t1.Month指定一个别名,例如num:


你能解释一下输出中SUB列的计算吗?Postgres实际上没有dataframe的概念。这些信息在表格中吗?对不起,我已经习惯了R,所以我把所有的东西都称为数据帧。是的,我的意思是桌子。你错过了12个月sub的滞后1;我做了类似的事情,但我同时使用了分区和覆盖。“我会让这一点运行一点,”戈登林诺夫-谢谢,你的答案是更好的一个无论如何;这很有魅力。我是一个新的窗口条款的大风扇-它已经派上用场几次了。
  1 2 3 4 5
 +---------+
1|O . . . .|
2|O O . . .|
3|O O O . .|
4|. O O O .|
5|. . O O O|
 +---------+
year    month   subs
2014        1       5
2014        2       3
2014        3       3
2014        4       2
2014        5       5
2014        6       2
2014        7       6
2014        8       2
2014        9       2
2014        10      7
2014        11      2
2014        12      4
2015        1       1
alter table Test add column num int NULL

update Test
set num = (Year-2014)*12+Month

select
    t1.Year,
    t1.Month,
    sum(case when t2.num <= t1.num and t2.num - t1.num > -1 then 1 else 0 end * t2.one_ms) +
    sum( case when t2.num <= t1.num and t2.num - t1.num > -3 then 1 else 0 end * t2.three_ms ) +
    sum( case when t2.num <= t1.num and t2.num - t1.num > -12 then 1 else 0 end * t2.twelve_ms ) as subs
from Test t1
    join Test t2
        on 1=1
group by t1.Year, t1.Month, t1.num
order by t1.num