我们有一个像天的表:
ID Date
1 2015-07-29
2 2015-07-30
3 2015-07-31
4 2015-08-01
5 2015-08-03
7 2015-08-04
8 2015-08-05
9 2015-08-06
10 2015-08-07
11 2015-08-10
我们希望找到所有序列(第+ 1天)。结果应该是这样的:
Start End
2015-07-29 2015-08-01
2015-08-03 2015-08-07
2015-08-10 2015-08-10
1。更新
首先我修改了Deepanshu Kalra的答案,使用RowNumber代替Id(Id是自动增量,因此可能缺少id)
DECLARE @P TABLE(DATE DATE)
INSERT INTO @P
SELECT MIN([DATE])
FROM MietvertragsArtikelDays
UNION
SELECT T1.[DATE]
FROM (SELECT ROW_NUMBER() OVER (ORDER BY [DATE]) RowNumber, [DATE] FROM MietvertragsArtikelDays) AS T1 INNER JOIN (SELECT ROW_NUMBER() OVER (ORDER BY [DATE]) RowNumber, [DATE] FROM MietvertragsArtikelDays) AS T2 ON T1.RowNumber=T2.RowNumber+1
WHERE DATEDIFF(DAY,T2.[DATE],T1.[DATE]) <>1
UNION
SELECT T2.[DATE]
FROM (SELECT ROW_NUMBER() OVER (ORDER BY [DATE]) RowNumber, [DATE] FROM MietvertragsArtikelDays) AS T1 INNER JOIN (SELECT ROW_NUMBER() OVER (ORDER BY [DATE]) RowNumber, [DATE] FROM MietvertragsArtikelDays) AS T2 ON T1.RowNumber=T2.RowNumber+1
WHERE DATEDIFF(DAY,T2.[DATE],T1.[DATE]) <>1
DECLARE @X TABLE(DATE DATE, RN INT)
INSERT INTO @X
SELECT *, ROW_NUMBER() OVER(ORDER BY [DATE]) AS X FROM @P
SELECT A.[DATE] Start, ISNULL(B.[DATE],A.[DATE]) [End] FROM @X A
LEFT JOIN (SELECT [DATE], RN-1 AS RN FROM @X) B
ON A.RN=B.RN
WHERE A.RN%2=1
2。更新
最优雅的解决方案是Ughais
;WITH CTE as
(
SELECT *,DATEDIFF(D,0,[Date]) - ROW_NUMBER()OVER(ORDER BY ID ASC) grp
FROM MietvertragsArtikelDays
)
SELECT MIN([Date]),MAX([Date])
FROM CTE
GROUP BY grp
答案 0 :(得分:4)
这是Islands and Gap problem。您可以使用ROW_NUMBER
和DATEDIFF
。这样的事情。
<强> SQL Fiddle 强>
示例数据
DECLARE @Dates TABLE
([ID] int, [Date] datetime);
INSERT INTO @Dates
([ID], [Date])
VALUES
(1, '2015-07-29 00:00:00'),
(2, '2015-07-30 00:00:00'),
(3, '2015-07-31 00:00:00'),
(4, '2015-08-01 00:00:00'),
(5, '2015-08-03 00:00:00'),
(7, '2015-08-04 00:00:00'),
(8, '2015-08-05 00:00:00'),
(9, '2015-08-06 00:00:00'),
(10, '2015-08-07 00:00:00'),
(11, '2015-08-10 00:00:00');
<强>查询强>
;WITH CTE as
(
SELECT *,DATEDIFF(D,0,[Date]) - ROW_NUMBER()OVER(ORDER BY ID ASC) grp
FROM @Dates
)
SELECT MIN([Date]),MAX([Date])
FROM CTE
GROUP BY grp
<强>输出强>
2015-07-29 00:00:00.000 2015-08-01 00:00:00.000
2015-08-03 00:00:00.000 2015-08-07 00:00:00.000
2015-08-10 00:00:00.000 2015-08-10 00:00:00.000
答案 1 :(得分:1)
当我从已经发布的答案开始时,也许我把它变得非常复杂。但它确实有效。
DECLARE @T TABLE(ID INT, DATE DATE)
INSERT INTO @T
SELECT 1, '2015-07-29' UNION ALL
SELECT 2, '2015-07-30' UNION ALL
SELECT 3, '2015-07-31' UNION ALL
SELECT 4, '2015-08-01' UNION ALL
SELECT 5, '2015-08-03' UNION ALL
SELECT 7, '2015-08-04' UNION ALL
SELECT 8, '2015-08-05' UNION ALL
SELECT 9, '2015-08-06' UNION ALL
SELECT 10, '2015-08-07' UNION ALL
SELECT 11, '2015-08-10'
DECLARE @P TABLE(DATE DATE)
INSERT INTO @P
SELECT MIN([DATE])
FROM @T
UNION
SELECT T1.[DATE]
FROM @T AS T1 INNER JOIN @T AS T2 ON T1.ID=T2.ID+1
WHERE DATEDIFF(DAY,T2.[DATE],T1.[DATE]) <>1
UNION
SELECT T2.[DATE]
FROM @T AS T1 INNER JOIN @T AS T2 ON T1.ID=T2.ID+1
WHERE DATEDIFF(DAY,T2.[DATE],T1.[DATE]) <>1
DECLARE @X TABLE(DATE DATE, RN INT)
INSERT INTO @X
SELECT *, ROW_NUMBER() OVER(ORDER BY [DATE]) AS X FROM @P
SELECT A.[DATE], B.[DATE] FROM @X A
LEFT JOIN (SELECT [DATE], RN-1 AS RN FROM @X) B
ON A.RN=B.RN
WHERE A.RN%2=1
请原谅标准和所有。将在当天晚些时候进行编辑。对不起。
答案 2 :(得分:0)
无论Id的顺序和价值如何,这都将有效:
Declare @dates table(ID int, D datetime)
Insert Into @dates(ID, D)
values (1, '2015-07-29')
, (2, '2015-07-30')
, (3, '2015-07-31')
, (4, '2015-08-01')
, (5, '2015-08-03')
, (7, '2015-08-04')
, (8, '2015-08-05')
, (9, '2015-08-06')
, (10, '2015-08-07')
, (11, '2015-08-10')
; With start(ID, D) as (
-- Get 1st Dates
Select d1.ID, d1.D From @dates as d1
Left Join @dates as d2 On d1.D = DATEADD(DAY, 1, d2.D)
Where d2.ID is NULL
), loop(startD, endD) as (
-- Loop through consecutives dates
Select D, D From start
Union All
Select l.startD, s.D From loop as l
Inner Join @dates as s On s.D = DATEADD(DAY, 1, l.endD)
)
-- Get max end date for each start date
Select startD as [Start], max(endD) as [End] From loop group by startD
输出:
Start End
2015-07-29 2015-08-01
2015-08-03 2015-08-07
2015-08-10 2015-08-10