需要帮助才能从小组

时间:2015-05-30 08:55:56

标签: sql-server sql-server-2012

PFB剧本

CREATE TABLE LagLead
(
    ID INT
    ,Flag TINYINT
    ,DateCreated DATETIME
)

GO

INSERT INTO LagLead
SELECT 100,0,'May 30 2000 11:37AM'
UNION ALL
SELECT 100,0,'May 30 2001 11:37AM'
UNION ALL
SELECT 100,0,'May 30 2002 11:37AM'
UNION ALL
SELECT 100,1,'May 30 2003 11:37AM'
UNION ALL
SELECT 100,1,'May 30 2004 11:37AM'
UNION ALL
SELECT 100,1,'May 30 2005 11:37AM'
UNION ALL
SELECT 100,0,'May 30 2006 11:37AM'
UNION ALL
SELECT 100,0,'May 30 2007 11:37AM'
UNION ALL
SELECT 100,0,'May 30 2008 11:37AM'
UNION ALL
SELECT 101,1,'May 30 2004 11:37AM'
UNION ALL
SELECT 101,1,'May 30 2005 11:37AM'
UNION ALL
SELECT 102,0,'May 30 2004 11:37AM'

来源表记录:

enter image description here

我需要输出类似下面查询的输出,但需要摆脱脚本中存在的硬编码2和9。感谢

预期产出:

enter image description here

我已尝试使用此脚本但需要将其设置为动态(删除硬编码2,9)

SELECT ID,Flag,Lag AS StartDate,Lead AS EndDate FROM
(
SELECT *
,CASE WHEN Flag != LEAD(Flag,1,9) OVER (PARTITION BY ID ORDER BY DateCreated) THEN 1 ELSE 0 END AS LeadFlag
,LAG(DateCreated,2,DateCreated) OVER (PARTITION BY ID ORDER BY DateCreated) AS Lag
,LEAD(DateCreated,1,DateCreated) OVER (PARTITION BY ID ORDER BY DateCreated) AS Lead
   FROM LagLead
)src
WHERE LeadFlag = 1

使用滞后/导联功能并非强制性。

1 个答案:

答案 0 :(得分:1)

我做到了没有滞后和领导。

with cte as (
    select row_number() over (order by id, DateCreated) as r, 
       row_number() over (partition by id, flag order by id, DateCreated) as pr
       , * 
    from LagLead
), grouped as (
    select *, r - pr as g
    from cte
)

select id, flag, min(DateCreated), max(DateCreated)
from grouped
group by id, flag, g
order by id, min(DateCreated)

你当然可以在一个cte中做到这一点,但我发现这种风格更具说明性。作为解释,我正在创建两个“虚拟”列 - 一个枚举整个集合,另一个枚举具有相同id和标志值的行集合中的行(两者都由同一组列排序)。关键的观察是,只要标志值不会在行之间发生变化,这两个列都会增加1,因此它们之间的差异在行之间是相同的。然而,一旦(id,flag)的组合改变,第一row_number和第二row_number将增加不同的值,因此两者之间的差异将与前一行不同。这有助于为我们提供便利的分组价值。顺便说一句,这类问题通常被称为“间隙和岛屿”。