将表拆分为具有重复属性的Windows

时间:2019-03-07 21:41:10

标签: sql sql-server tsql window-functions

我的头衔太糟糕了,因为我不确定如何描述挑战。如果有人可以想到更具描述性的标题,我希望进行编辑。希望我的输入/期望的输出将有助于解释。这是一些示例输入数据:

create table #input (
    num varchar(10),
    code varchar(10),
    event_date date
)

insert into #input (num, code, event_date)
values('123456', 'Active', '2007-09-10'),
      ('123456', 'Active', '2010-09-15'),
      ('123456', 'Active', '2010-09-24'),
      ('123456', 'Inactive', '2018-09-17'),
      ('123456', 'Inactive', '2019-01-01'),
      ('123456', 'Active', '2019-02-08')

select *
from #input
order by event_date

我想用相同的数字标记每组num +代码的每条记录。但是,我希望时间段保持分开。这是预期的结果:

create table #result (
    num varchar(10),
    code varchar(10),
    event_date date,
    tag int
)

insert into #result (num, code, event_date, tag)
values('123456', 'Active', '2007-09-10', 1),
      ('123456', 'Active', '2010-09-15', 1),
      ('123456', 'Active', '2010-09-24', 1),
      ('123456', 'Inactive', '2018-09-17', 2),
      ('123456', 'Inactive', '2019-01-01', 2),
      ('123456', 'Active', '2019-02-08', 3)

select *
from #result
order by event_date

像这样的普通窗口分区...

select *, row_number() over(partition by num, code order by event_date) rn
from #input
order by event_date

...不起作用,因为没有要分割两个“活动”组(两个组,因为它们在两个时间段内发生)的分区字段。我如何达到理想的结果?我有一个预感,一系列lag()lead()函数可能会起作用,但是我无法获得有意义的地方。

或者,我将如何获得结果,以使类别重叠一个?

create table #result_new (
    num varchar(10),
    code varchar(10),
    event_date date,
    tag int
)

insert into #result (num, code, event_date, tag)
values('123456', 'Active', '2007-09-10', 1),
      ('123456', 'Active', '2010-09-15', 1),
      ('123456', 'Active', '2010-09-24', 1),
      ('123456', 'Inactive', '2018-09-17', 1),
      ('123456', 'Inactive', '2019-01-01', 2),
      ('123456', 'Active', '2019-02-08', 2)

select *
from #result_new
order by event_date

1 个答案:

答案 0 :(得分:3)

LAG可以到达一半,但不能完全到达一半。您可以使用LAG检查最后一行的值,并创建(我称之为)开关。然后,您可以使用带有SUM子句的ROWs BETWEEN窗口函数来获取tag的值:

WITH CTE AS(
      SELECT num,
             code,
             event_date,
             CASE WHEN code = LAG(code) OVER (PARTITION BY num ORDER BY event_date) THEN 0 ELSE 1 END AS Switch
      FROM #input)
SELECT num,
       code,
       event_date,
       SUM(Switch) OVER (PARTITION BY num ORDER BY event_date
                         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS tag
FROM CTE;
相关问题