SQL 服务器中基于条件行分组的列值相乘
Multiplication of column values based on conditional row grouping in SQL Server
对于上述数据,我想根据行的分组计算每个购买行(purchase = 1)的百分比值。
计算条件为:
- 前几行的 visit_time 应在购买后 7 天内 visit_time。
- 具有相同访问者 ID 的行应仅在计算中考虑。
例如,百分比值应计算如下:
- 第 2 行 Percent_val = 第 1 行的值 x 第 2 行的值 = 0.23 x 0.97 = 0.2231
- 第 3 行 Percent_val = 第 1 行的值 x 第 2 行的值 x 第 3 行的值 = 0.23 x 0.97 x 0.55 = 0.122705
- 第 4 行 Percent_val = 第 4 行的值 = 0.11
- 第 7 行 Percent_val = 第 5 行的值 x 第 6 行的值 x 第 7 行的值 = 0.57 x 0.16 x 0.38 = 0.034656(不会考虑第 4 行,因为它 visit_time 是不在购买行的 7 天范围内,即第 7 行)
我正在使用 SQL Server 2012。
预期结果将类似于以下内容:
这里如何得到预期的结果?
生成测试数据的脚本:
CREATE TABLE [#tmp_data]
(
[visitor] INT,
[visit_id] INT,
[visit_time] DATETIME,
[val] numeric(4,2),
[purchase] BIT
);
INSERT INTO #tmp_data( visitor, visit_id, visit_time,val, purchase )
VALUES( 1, 1001, '2020-01-01 10:00:00', 0.23,0 ),
( 1, 1002, '2020-01-02 11:00:00', 0.97,1 ),
( 1, 1003, '2020-01-02 14:00:00', 0.55, 1 ),
( 2, 2001, '2020-01-01 10:00:00', 0.11, 1 ),
( 2, 2002, '2020-01-07 11:00:00', 0.57, 0 ),
( 2, 2003, '2020-01-08 14:00:00', 0.16, 0 ),
( 2, 2004, '2020-01-11 14:00:00', 0.38, 1 );
在 SQL 服务器中,一个选项使用横向连接:
select t.*, x.percent_val
from #tmp_data t
cross apply (
select exp(sum(log(t1.val))) percent_val
from #tmp_data t1
where t1.visitor = t.visitor and t1.visit_time > dateadd(day, - 7, t.visit_time) and t1.visit_time <= t.visit_time
) x
where t.purchase = 1
横向连接恢复同一访客过去 7 天的访问。然后,我们使用算术来计算值的总乘积(只要 val
大于 0
,这就有效)。
visitor | visit_id | visit_time | val | purchase | percent_val
------: | -------: | :---------------------- | ---: | :------- | ----------:
1 | 1002 | 2020-01-02 11:00:00.000 | 0.97 | True | 0.2231
1 | 1003 | 2020-01-02 14:00:00.000 | 0.55 | True | 0.122705
2 | 2001 | 2020-01-01 10:00:00.000 | 0.11 | True | 0.11
2 | 2004 | 2020-01-11 14:00:00.000 | 0.38 | True | 0.034656
如果您还想处理 0
值,那么您可以更改 suquery 的 select
子句:
select case when min(val) = 0
then 0
else exp(sum(log(case when val > 0 then t1.val end)))
end percent_val
对于上述数据,我想根据行的分组计算每个购买行(purchase = 1)的百分比值。
计算条件为:
- 前几行的 visit_time 应在购买后 7 天内 visit_time。
- 具有相同访问者 ID 的行应仅在计算中考虑。
例如,百分比值应计算如下:
- 第 2 行 Percent_val = 第 1 行的值 x 第 2 行的值 = 0.23 x 0.97 = 0.2231
- 第 3 行 Percent_val = 第 1 行的值 x 第 2 行的值 x 第 3 行的值 = 0.23 x 0.97 x 0.55 = 0.122705
- 第 4 行 Percent_val = 第 4 行的值 = 0.11
- 第 7 行 Percent_val = 第 5 行的值 x 第 6 行的值 x 第 7 行的值 = 0.57 x 0.16 x 0.38 = 0.034656(不会考虑第 4 行,因为它 visit_time 是不在购买行的 7 天范围内,即第 7 行)
我正在使用 SQL Server 2012。
预期结果将类似于以下内容:
这里如何得到预期的结果?
生成测试数据的脚本:
CREATE TABLE [#tmp_data]
(
[visitor] INT,
[visit_id] INT,
[visit_time] DATETIME,
[val] numeric(4,2),
[purchase] BIT
);
INSERT INTO #tmp_data( visitor, visit_id, visit_time,val, purchase )
VALUES( 1, 1001, '2020-01-01 10:00:00', 0.23,0 ),
( 1, 1002, '2020-01-02 11:00:00', 0.97,1 ),
( 1, 1003, '2020-01-02 14:00:00', 0.55, 1 ),
( 2, 2001, '2020-01-01 10:00:00', 0.11, 1 ),
( 2, 2002, '2020-01-07 11:00:00', 0.57, 0 ),
( 2, 2003, '2020-01-08 14:00:00', 0.16, 0 ),
( 2, 2004, '2020-01-11 14:00:00', 0.38, 1 );
在 SQL 服务器中,一个选项使用横向连接:
select t.*, x.percent_val
from #tmp_data t
cross apply (
select exp(sum(log(t1.val))) percent_val
from #tmp_data t1
where t1.visitor = t.visitor and t1.visit_time > dateadd(day, - 7, t.visit_time) and t1.visit_time <= t.visit_time
) x
where t.purchase = 1
横向连接恢复同一访客过去 7 天的访问。然后,我们使用算术来计算值的总乘积(只要 val
大于 0
,这就有效)。
visitor | visit_id | visit_time | val | purchase | percent_val ------: | -------: | :---------------------- | ---: | :------- | ----------: 1 | 1002 | 2020-01-02 11:00:00.000 | 0.97 | True | 0.2231 1 | 1003 | 2020-01-02 14:00:00.000 | 0.55 | True | 0.122705 2 | 2001 | 2020-01-01 10:00:00.000 | 0.11 | True | 0.11 2 | 2004 | 2020-01-11 14:00:00.000 | 0.38 | True | 0.034656
如果您还想处理 0
值,那么您可以更改 suquery 的 select
子句:
select case when min(val) = 0
then 0
else exp(sum(log(case when val > 0 then t1.val end)))
end percent_val