将事件后的多次重复计为单次重复

时间:2014-05-20 20:13:34

标签: sql sql-server tsql sql-server-2008-r2

我正在努力想出一个可以在初始事件发生后的30天内给出重复百分比的查询,但只计算30天内任何事件作为单个重复。这是一个人的样本数据集:

人日期
══════════════
 A 3/1/14
 A 3/21/14
 A 3/29/14
 A 4/14/14
 2014年4月17日

在这种情况下,3/21将是重复事件,而3/29不会被计为秒。 4/14将是下一个窗口的开始,4/17是第二个重复。

要计算此处重复的百分比,分子将是在该月内具有初始事件且在30天内发生后续事件的人的独特计数。分母是当月发生事件的人数。在跨越月份的情况下,重复计算在初始事件的月份内。

我知道我可以想出一些使用循环/光标或临时表的东西,但随着数据集的增长,它将需要永远。有没有人对如何将此作为单个查询有任何想法?它可能涉及几个CTE。到目前为止我提出的所有事情都失败了。

1 个答案:

答案 0 :(得分:1)

很好...试试这个:

create table #t (Person varchar(10), EventDate date);
insert #t (Person, EventDate)
values
('A', '3/1/14'),
('A', '3/21/14'),
('A', '3/29/14'),
('A', '4/14/14'),
('A', '4/17/14'),
('A', '8/3/14'),
('B', '3/25/14'),
('B', '4/2/14'),
('B', '4/20/14'),
('B', '6/14/14'),
('B', '8/17/14'),
('B', '8/26/14');
;WITH OrderedEvents AS (
    SELECT  Person, EventDate, ROW_NUMBER() OVER (PARTITION BY Person ORDER BY EventDate) AS Ord
    FROM    #t
)
, RepeatedEvents AS (
    SELECT  Person, EventDate, Ord, EventDate AS InitialDate
    FROM    OrderedEvents
    WHERE   Ord = 1
    UNION ALL
    SELECT  o.Person, o.EventDate, o.Ord
            , CASE WHEN DATEDIFF(DAY, r.InitialDate, o.EventDate) > 30 THEN o.EventDate ELSE r.InitialDate END
    FROM    OrderedEvents o
            JOIN RepeatedEvents r ON o.Person = r.Person AND o.Ord = r.Ord + 1
)
, GroupedEvents AS (
    SELECT  Person, MONTH(InitialDate) AS Mth, YEAR(InitialDate) AS Yr
            , IsRepeat = CASE WHEN COUNT(*) > 1 THEN 1 ELSE 0 END
    FROM    RepeatedEvents
    GROUP BY Person, MONTH(InitialDate), YEAR(InitialDate)
)
SELECT  Mth, Yr, CAST(SUM(IsRepeat) AS NUMERIC) / CAST(COUNT(DISTINCT person) AS NUMERIC) AS Pct
FROM    GroupedEvents 
GROUP BY Mth, Yr;