SQL Server - 有条件地增加计数器

时间:2016-02-11 15:28:35

标签: sql sql-server

我要做的是为连续日期范围创建分组序列。获取以下示例数据:

Person|BeginDate |EndDate
A     |1/1/2015  |1/31/2015
A     |2/1/2015  |2/28/2015
A     |4/1/2015  |4/30/2015
A     |5/1/2015  |5/31/2015
B     |1/1/2015  |1/30/2015
B     |8/1/2015  |8/30/2015
B     |9/1/2015  |9/30/2015

如果当前行中的BeginDate距离上一行的EndDate大于1天,则将计数器递增1,否则指定计数器的当前值。测序看起来像:

Person|BeginDate |EndDate  |Sequence
A     |1/1/2015  |1/31/2015|1
A     |2/1/2015  |2/28/2015|1
A     |4/1/2015  |4/30/2015|2
A     |5/1/2015  |5/31/2015|2
B     |1/1/2015  |1/30/2015|1
B     |8/1/2015  |8/30/2015|2
B     |9/1/2015  |9/30/2015|2

为每个人分区并重置。

为了您的测试:

 CREATE TABLE ##SequencingTest(
 Person char(1)
,BeginDate date
,EndDate date)

INSERT INTO ##SequencingTest
VALUES
('A','1/1/2015','1/31/2015')
,('A','2/1/2015','2/28/2015')
,('A','4/1/2015','4/30/2015')
,('A','5/1/2015','5/31/2015')
,('B','1/1/2015','1/30/2015')
,('B','8/15/2015','8/31/2015')
,('B','9/1/2015','9/30/2015')

2 个答案:

答案 0 :(得分:3)

您可以使用lag()然后累积总和来执行此操作:

select t.*,
       sum(flag) over (partition by person order by begindate) as sequence
from (select t.*,
             (case when datediff(day, lag(endDate) over (partition by person order by begindate), begindate) < 2
                   then 0
                   else 1
              end) as flag
      from t
     ) t;

答案 1 :(得分:2)

如果连续结束日期总是在下一个开始日期前1天,你可以做一些非常原始的事情:

SELECT S1.Person, S1.BeginDate, S1.EndDate, SUM(S2.Cntr) AS Sequence
FROM Sequencing S1
INNER JOIN (SELECT Person, BeginDate,
      CASE WHEN EXISTS (SELECT Person FROM Sequencing S2 WHERE S2.[EndDate] =
            DATEADD(d, -1, S1.[BeginDate]) AND S2.Person = S1.Person) THEN 0 ELSE 1 END AS Cntr
      FROM [Sequencing] S1
     ) S2
  ON S1.Person = S2.Person
  AND S1.BeginDate >= S2.BeginDate
GROUP BY S1.Person, S1.BeginDate, S1.EndDate
ORDER BY S1.Person, S1.BeginDate, S1.EndDate

注意我想你想说的是2015年1月31日&#39;和&#39; 8/31/2015&#39;作为结束日期与你的例子一起工作。

另外,@ GordonLinoff的回答可能更好。我根本就没有SQL Server的版本来测试它。