【问题标题】:Multiplication of column values based on conditional row grouping in SQL ServerSQL Server 中基于条件行分组的列值乘法
【发布时间】:2021-01-13 18:58:45
【问题描述】:

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

计算条件为:

  1. 前几行的visit_time应在购买visit_time的7天内。
  2. 仅应在计算中考虑具有相同访客 ID 的行。

例如,百分比值应计算如下:

  • 第 2 行 Percent_val = 第 1 行的 val x 第 2 行的 val = 0.23 x 0.97 = 0.2231
  • 第 3 行 Percent_val = 第 1 行的 val x 第 2 行的 val x 第 3 行的 val = 0.23 x 0.97 x 0.55 = 0.122705
  • 第 4 行 Percent_val = 第 4 行的 val = 0.11
  • 第 7 行 Percent_val = 第 5 行的 val x 第 6 行的 val x 第 7 行的 val = 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 sql-server tsql datetime sql-server-2012


    【解决方案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

    访客 |访问ID |访问时间 |值 |购买 | percent_val ------: | --------: | :------------------------ | ---: | :------- | ----------: 1 | 1002 | 2020-01-02 11:00:00.000 | 0.97 |真 | 0.2231 1 | 1003 | 2020-01-02 14:00:00.000 | 0.55 |真 | 0.122705 2 | 2001 | 2020-01-01 10:00:00.000 | 0.11 |真 | 0.11 2 | 2004 | 2020-01-11 14:00:00.000 | 0.38 |真 | 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
    

    【讨论】:

    • 谢谢,这有效,但正如您在 val > 0 时提到的那样。但是,我有 0 值的 val 数据,在这种情况下,它不起作用。
    • @Samay:在这种情况下你想要哪个结果?
    • 感谢您的回复。当 val = 0 时,percent_val 值应为 0。例如如果第 4 行的 val = 0,那么第一次购买的访客 2 的 percent_val 计算应该为 0。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 2011-04-08
    • 2018-08-22
    • 2022-10-15
    • 1970-01-01
    相关资源
    最近更新 更多