sql - SQL Server 中基于条件行分组的列值相乘

标签 sql sql-server t-sql datetime sql-server-2012

enter image description here

对于上述数据,我想根据对行进行分组来计算每个购买行 (purchase = 1) 的百分比值。

计算条件为:

  1. 前几行的访问时间应在购买访问时间后 7 天内。
  2. 计算时应仅考虑具有相同访问者 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 行的 val x 第 6 行的 val x 第 7 行的 val = 0.57 x 0.16 x 0.38 = 0.034656 (第 4 行不会被考虑,因为它的访问时间不在购买行的 7 天范围内,即行7)

我使用的是 SQL Server 2012。

预期结果类似于以下内容:

enter image description here

如何在这里得到预期的结果?

生成测试数据的脚本:

    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 Server 中,一个选项使用横向联接:

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 就有效)。

<强> Demo on DB Fiddle :

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

If you want to handle 0 values as well, then you can change the select clause of the suquery:

select case when min(val) = 0 
    then 0 
    else exp(sum(log(case when val > 0 then t1.val end))) 
end percent_val

关于sql - SQL Server 中基于条件行分组的列值相乘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64098023/

相关文章:

mysql - 使用错误的引号样式运行 SQL 语句

MySQL:不要选择在其他联接中匹配的记录

sql-server - 按月份名称而不是月份编号获取开始和结束日期

sql-server - 在 SQL Server 中按名称查找过程或表

sql - 无法加载资源文件 sqlcmd.rll

sql - 如何通过 PSQL ( postgresql ) 将 select 语句输出存储到变量中

SQL - 查询存储不一致的电话号码

sql - 旋转两列,保持表中的其他列不变

sql-server - 用于复制记录的 TSQL 存储过程(有一点不同!)

sql-server - SSIS 联合全部 vs sql server 联合全部