每周事件不间断发生

时间:2018-01-25 15:46:56

标签: sql-server

declare @t table([CH_FMT_ID] nvarchar(3),[CH_ISS_DT] date,[CH_RANK] int,[CH_TTL_ID] bigint)

INSERT INTO @t values 
('HSI', '6/15/2002',    28, 397130),
('HSI', '6/8/2002', 24, 397130),
('HSI', '6/1/2002', 23, 397130),
('HSI', '5/25/2002',    20, 397130),
('HSI', '5/18/2002',    13, 397130),
('HSI', '5/11/2002',    12, 397130),
('HSI', '5/4/2002', 11, 397130),
('HSI', '6/15/2002',    28  ,   111111),
('HSI', '6/8/2002', 24  ,   111111),
('HSI', '6/1/2002', 23  ,   111111),
('HSI', '5/25/2002',    20  ,   111111),
('HSI', '5/18/2002',    13  ,   111111),
('HSI', '5/11/2011',    12  ,   111111),
('HSI', '5/4/2011', 11  ,   111111);


SELECT chart.CH_TTL_ID
,chart.[CH_FMT_ID] Chart
,min(chart.[CH_RANK]) Peak
,max(chart.[CH_RANK]) Trough
,count(chart.[CH_RANK]) Weeks
,MIN(chart.CH_ISS_DT) EntryDate
,MAX(chart.CH_ISS_DT) ExitDate
,(DATEDIFF(day, MIN(CH_ISS_DT),MAX(CH_ISS_DT)) / 7) Weeks_Charted
FROM @t chart
group by chart.CH_TTL_ID
,chart.[CH_FMT_ID]
order by Weeks_Charted desc

CH_ISS_DT是一个更新1x /周的日期。所以日期是2017-12-31,2017-12-24,2017-12-12等。问题来自Weeks_Charted专栏。如果在2007年第一次发生某些事情并且直到2017年才会再次发生,那么Weeks_Charted将计算两者之间的所有周,即使数据不是一直存在。

此示例返回:

CH_TTL_ID,Chart,Peak,Trough,Weeks,EntryDate,ExitDate,Weeks_Charted
111111,HSI,11,28,7,2002-05-18,2011-05-11,468
397130,HSI,11,28,7,2002-05-04,2002-06-15,6

如果CH_TTL_ID返回2行,其中一行为2,为week_charted,另一行为5,或者只返回最近的数据为2,则max,mins不同,我无动于衷。

1 个答案:

答案 0 :(得分:1)

尝试此查询。连续几周查询群组。

select
    CH_TTL_ID, CH_FMT_ID Chart
    ,min([CH_RANK]) Peak
    ,max([CH_RANK]) Trough
    ,count([CH_RANK]) Weeks
    ,MIN(CH_ISS_DT) EntryDate
    ,MAX(CH_ISS_DT) ExitDate
from (
    select
        *, sum(N) over (partition by CH_TTL_ID order by CH_ISS_DT) grp
    from (
        select 
            *, iif(datediff(dd, lag(CH_ISS_DT) over (partition by CH_TTL_ID order by CH_ISS_DT), CH_ISS_DT) = 7, 0, 1) N
        from 
            @t chart
    ) t
) t
group by CH_TTL_ID, CH_FMT_ID, grp

一种选择是在SQL 2008中使用Recursive CTE来解决此类问题

;with cte as (
    select 
        *,row_number() over (partition by CH_TTL_ID, CH_FMT_ID order by CH_ISS_DT) rn
    from
        @t chart
)
, rcte as (
    select
        *, 1 grp
    from
        cte
    where
        rn = 1
    union all
    select
        a.CH_FMT_ID, b.CH_ISS_DT, b.CH_RANK, a.CH_TTL_ID, b.rn, a.grp + case when datediff(dd, a.CH_ISS_DT, b.CH_ISS_DT) = 7 then 0 else 1 end
    from
        rcte a
        join cte b on a.CH_FMT_ID = b.CH_FMT_ID and a.CH_TTL_ID = b.CH_TTL_ID and a.rn + 1 = b.rn
)

select
    CH_TTL_ID, CH_FMT_ID Chart
        ,min([CH_RANK]) Peak
        ,max([CH_RANK]) Trough
        ,count([CH_RANK]) Weeks
        ,MIN(CH_ISS_DT) EntryDate
        ,MAX(CH_ISS_DT) ExitDate
from
    rcte
group by CH_TTL_ID, CH_FMT_ID, grp
order by CH_FMT_ID, CH_TTL_ID

option (maxrecursion 0)