从天开始获取天数

时间:2015-08-10 08:47:21

标签: sql tsql

我们有一个像天的表:

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

3 个答案:

答案 0 :(得分:4)

这是Islands and Gap problem。您可以使用ROW_NUMBERDATEDIFF。这样的事情。

<强> 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