T-SQL聚合窗口在特定时间间隔内的功能

时间:2017-04-15 18:36:50

标签: sql sql-server tsql group-by window-functions

这是一个SQL 2012表:

CREATE TABLE [dbo].[TBL_BID]
(
    [ID] [varchar](max) NULL,
    [VALUE] [smallint] NULL,
    [DT_START] [date] NULL,
    [DT_FIN] [date] NULL
)

我可以通过LAG窗口函数,以及事件总数(或过去事件的特定数量),每个用户的总平均值等轻松获取上一个事件的值,自上次事件以来的时间(或任何特定滞后) / p>

SELECT 
    ID,
    [VALUE],
    [DT_START], [DT_FIN],
    -- days since the end of last event
    DATEDIFF(d, LAG([DT_FIN], 1) OVER (PARTITION BY ID ORDER BY [DT_FIN]),
    [DT_START]) AS LAG1_DT,
    -- value of the last event
    LAG([VALUE], 1) OVER (PARTITION BY ID ORDER BY [DT_FIN]) AS LAG1_VALUE,
    -- number of events per id
    COUNT(ID) OVER (PARTITION BY ID) AS N,
    -- average [value] per id
    ROUND(AVG(CAST([VALUE] as float)) OVER (PARTITION BY ID), 1) AS VAL_AVG
FROM 
    TBL_BID

我正在尝试查看指定时间间隔发生的事件,即 10天,30天,180天等,在每个事件的开始日期之前

  • 事件数
  • 平均值[VALUE]
  • 事件结束与下一个事件开始之间的平均天数

有些事情:

COUNT(ID) OVER (PARTITION BY ID ORDER BY DT_FIN 
                RANGE BETWEEN DATEDIFF(d,-30,[DT_START]) AND [DT_START] )

更新4/19/2017: 一些统计数据 约20MM ID,时间间隔为5年, 每个ID的平均事件数为3.0。它可能是每个ID 100多个事件,但大多数只有少数事件,分布非常正确

Events_per_ID   Number_IDs
1   18676221
2   11254167
3   6992200
4   4487664
5   2933183
6   1957433
7   1330040
8   918873
9   644229
10  457858
........

2 个答案:

答案 0 :(得分:0)

最简单的方法是outer apply

select . . .,
       b.cnt_30
from TBL_BID b outer apply
     (select count(*) as cnt_30
      from TBL_BID b2
      where b2.id = b.id and
            b2.dt_start >= dateadd(day, -30, b.dt_start) and
            b2.dt_start <= b.dt_start
     ) b;

这不一定非常有效。您可以通过添加更多outer apply子查询来扩展它。

答案 1 :(得分:0)

需要更多信息,但基本思路是通过为每个ID生成完整的日期范围,将Windows函数类型从range转换为rows

  • 为每个ID生成相关的天数范围(min(dt_start)-180max(dt_start)
  • 使用上面的行集作为基础,并TBL_BIDid上的LEFT JOIN dt_fin(如果(id,dt_fin)不唯一,则首先聚合)
  • 使用Windows功能分区按ID顺序排列日期前180/30/10行和当前行