仅为SQL Server 2008寻求优化代码(因为Lag
和Lead
函数在SQL Server 2008中不可用)。对于以下要求。(上次记录结束日期可以为null或不为null)
业务规则是:
EndDate应该是下一个规则的开始日期,否则规则不应该被认为是连续的并且将被视为其他规则系列,如下面的示例所示,有三个系列因为第四个记录和7个记录规则已经制动。 / p>
RuleId Name StartDate EndDate
-----------------------------------------------------------
2 TP1 1/1/2015 00.00.00 1/31/2015 00.00.00
2 TP1 1/31/2015 00.00.00 2/28/2015 00.00.00
2 TP1 2/28/2015 00.00.00 3/15/2015 00.00.00
2 TP1 3/18/2015 00.00.00 11/28/2015 00.00.00
2 TP1 11/28/2015 00.00.00 4/30/2016 00.00.00
2 TP1 4/30/2016 00.00.00 10/5/2016 00.00.00
2 TP1 10/25/2016 00.00.00 11/15/2016 00.00.00
2 TP1 11/15/2016 00.00.00 Null
结果应该是
2 TP1 1/1/2015 00.00.00 3/15/2015 00.00.00
2 TP1 3/18/2015 00.00.00 10/5/2016 00.00.00
2 TP1 10/25/2016 00.00.00 Null
答案 0 :(得分:1)
您可以使用ROW_NUMBER()
执行PARTITION BY
,然后使用rn = rn + 1进行自我加入,并根据您的结果对DATEDIFF
进行分组。
尝试这样的事情
DECLARE @Rules TABLE(RuleId INT,Name CHAR(3), StartDate DATE, EndDate DATE)
INSERT INTO @Rules VALUES
(3 ,'TP3', '3/18/2015', '11/28/2015'),
(3 ,'TP3', '11/28/2015', '4/30/2016'),
(3 ,'TP3', '4/30/2016', '10/5/2016'),
(3 ,'TP3', '10/25/2016', '11/15/2016'),
(3 ,'TP3', '11/15/2016', null)
;WITH CTE AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY RuleID ORDER BY StartDate) rn,*
FROM @Rules
), CTE2 AS
(
SELECT ISNULL(DATEDIFF(day,C1.EndDate,C2.StartDate),0) diff,C1.*
FROM CTE C1
LEFT JOIN CTE C2 ON C1.rn + 1 = C2.rn
AND C1.RuleId = C2.RuleId
)
SELECT RuleId,Name,MIN(StartDate) StartDate,NULLIF(MAX(CASE WHEN EndDate IS NULL THEN '2999/12/31' ELSE EndDate END),'2999/12/31') EndDate
FROM
(
SELECT C2.Diff,C1.RuleId,C1.Name,C1.StartDate,C1.EndDate
FROM CTE2 C1
CROSS APPLY (SELECT ISNULL(SUM(Diff),0) Diff FROM CTE2 C2 WHERE C1.StartDate > C2.StartDate AND C1.RuleId = C2.RuleId) C2
) C
GROUP BY RuleId,Name,Diff
ORDER BY RuleId,Diff