我有一个带模式的表:
date | item_id | factor
----------------------
20180710 | 1 | 0.1
20180711 | 1 | 0.1
20180712 | 1 | 2
20180713 | 1 | 2
20180714 | 1 | 2
20180710 | 2 | 0.1
20180711 | 2 | 0.1
20180712 | 2 | 5
20180713 | 2 | 5
20180714 | 2 | 10
每个item_id的因子可以在任何日期更改。在每个日期,我需要计算该日期(包括该日期)之前每个item_id的所有不同因子的乘积,因此上表的最终输出应为:
date | id | cumulative_factor
20180710 | 1 | 0.1
20180711 | 1 | 0.1
20180712 | 1 | 0.2
20180713 | 1 | 0.2
20180714 | 1 | 0.2
20180710 | 2 | 0.1
20180711 | 2 | 0.1
20180712 | 2 | 0.5
20180713 | 2 | 0.5
20180714 | 2 | 5
逻辑:
在20180711上,对于id = 1,唯一因子仅为0.1,因此累积因子为0.1。
在20180714上,对于id = 1,不同因子是0.1和2,因此累积因子是0.1 * 2 = 0.2。
在20180714上,对于id = 2,不同因子为0.1、5和10,因此累积因子为0.1 * 5 * 10 = 5。
我尝试过
select a.id, a.date, b.cum_factor
from factor_table a
left join (
select id, date, ISNULL(EXP(SUM(distinct log_factor)),1) as cum_factor
from factor_table
where date < a.date
) b
on a.id=b.id and a.date = b.date
但是我得到了错误
找不到日期
答案 0 :(得分:1)
SQL Server中没有产品聚合函数。
但是,您可以使用EXP ( SUM ( LAG ( value ) ) )
请参考在线查询以获取评论
; with
cte as
(
-- this cte set the factor to 1 if it is same as previous row
-- as you wanted `product of distinct`
select *,
factor2 = CASE WHEN LAG(factor) OVER (PARTITION BY id
ORDER BY [date]) IS NULL
OR LAG(factor) OVER (PARTITION BY id
ORDER BY [date]) <> factor
THEN factor
ELSE 1
END
from factor_table
),
cte2 as
(
-- this cte peform SUM( LOG ( factor ) ) only. except EXP()
select *, factor3 = SUM(LOG(factor2)) OVER (PARTITION BY id
ORDER BY [date])
from cte
)
-- EXP() is not a window function, so it has to do it in separately in another level
select *, EXP(factor3) as cumulative_factor
from cte2
注意:LAG()需要SQL Server 2012或更高版本
答案 1 :(得分:1)
乘以与众不同的因子似乎有些错误。您可以使用窗口函数轻松地表达这一点:
select f.id, f.date, f.cum_factor
exp(sum(distinct log(log_factor) over (partition by f.id order by f.date)))
from factor_table f;
要解决distinct
上的限制:
select f.id, f.date, f.cum_factor
exp(sum(log(case when seqnum = 1 then log_factor end) over (partition by f.id order by f.date)))
from (select t.*,
row_number() over (partition by id, log_factor order by date) as seqnum
from factor_table f
) f;