我有两列包含开始日期和结束日期。
我想编写一个sql查询来计算句点的开头,如果它是上个月的延续+一天,如果我休息超过一天,那么我想从一开始就开始那个时期
Ref Start End
----------------------------
6931 01/01/12 31/01/12
6931 01/02/12 29/02/12
6931 01/03/12 31/03/12
6931 01/04/12 30/04/12
6931 01/05/12 31/05/12
6931 01/06/12 30/06/12
6931 01/07/12 31/07/12
6931 01/08/12 31/08/12
6931 01/09/12 30/09/12
6931 01/10/12 31/10/12
6931 01/11/12 30/11/12
6931 01/12/12 31/12/12
6931 01/01/13 31/01/13
6931 01/02/13 28/02/13
6931 01/03/13 31/03/13
6931 01/04/13 18/04/13
6931 01/05/13 31/05/13
6931 01/06/13 30/06/13
6931 01/07/13 11/07/13
理想情况下,上述数据集在查询工作时应具有以下值
Ref Start End
----------------------------
6931 01/01/12 18/04/13
6931 01/05/13 11/07/13
非常感谢您的帮助,如果上述情况没有任何意义,请提前告知我。
答案 0 :(得分:0)
诀窍是找到一种方法来识别属于同一时期的日期,然后在每个组上使用Min / Max。
;WITH PeriodEnd AS
( SELECT [Ref],[End]
FROM #Periods
WHERE DAY(DATEADD(D,1,[END])) <> 1 --Get [End] dates that don't land on the last of the month
UNION
SELECT [Ref],MAX([End])
FROM #Periods
GROUP BY [Ref] --Grab the last [End] for each [Ref], regardless of whether is lands on the last day of the month
),
PeriodGroups AS
( SELECT p.[Ref],p.[Start],p.[End],
COUNT(pe.[End])OVER(ORDER BY p.[Ref],p.[End] DESC) AS Grouper --Assign a unique number to the dates in each period
FROM #Periods p
LEFT JOIN PeriodEnd pe ON pe.[End] = p.[End]
)
SELECT [Ref],
[Start] = MIN([Start]),
[End] = MAX([End])
FROM PeriodGroups
GROUP BY Grouper,[Ref]
ORDER BY 1,2
编辑:基于Kevin Cook的反馈的增强功能。
答案 1 :(得分:0)
设置我们的测试数据(我添加了新的6941范围,涵盖4-1到7-30
DECLARE @Periods TABLE
(
Ref INT,
StartDate DATE,
EndDate DATE
)
INSERT INTO @Periods
VALUES
(6931 ,'01/01/2012' ,'01/31/2012'),
(6931 ,'02/01/2012' ,'02/29/2012'),
(6931 ,'03/01/2012' ,'03/31/2012'),
(6931 ,'04/01/2012' ,'04/30/2012'),
(6931 ,'05/01/2012' ,'05/31/2012'),
(6931 ,'06/01/2012' ,'06/30/2012'),
(6931 ,'07/01/2012' ,'07/31/2012'),
(6931 ,'08/01/2012' ,'08/31/2012'),
(6931 ,'09/01/2012' ,'09/30/2012'),
(6931 ,'10/01/2012' ,'10/31/2012'),
(6931 ,'11/01/2012' ,'11/30/2012'),
(6931 ,'12/01/2012' ,'12/31/2012'),
(6931 ,'01/01/2013' ,'01/31/2013'),
(6931 ,'02/01/2013' ,'02/28/2013'),
(6931 ,'03/01/2013' ,'03/31/2013'),
(6931 ,'04/01/2013' ,'04/18/2013'),
(6931 ,'05/01/2013' ,'05/31/2013'),
(6941 ,'04/01/2013' ,'07/30/2013'),
(6931 ,'07/01/2013' ,'07/11/2013');
这里我们得到我们正在使用的数据的日期范围
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SELECT @StartDate = MIN(StartDate) FROM @Periods
SELECT @EndDate = MAX(EndDate) FROM @Periods
下一部分创建一个数字表来生成范围的所有日期,然后我们将获取id,行号和日期偏移组我们的数据。
DECLARE @number_of_numbers INT = 100000;
;WITH
a AS (SELECT 1 AS i UNION ALL SELECT 1),
b AS (SELECT 1 AS i FROM a AS x, a AS y),
c AS (SELECT 1 AS i FROM b AS x, b AS y),
d AS (SELECT 1 AS i FROM c AS x, c AS y),
e AS (SELECT 1 AS i FROM d AS x, d AS y),
f AS (SELECT 1 AS i FROM e AS x, e AS y),
numbers AS
(
SELECT TOP(@number_of_numbers)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS number
FROM f
),
dt AS
(
SELECT DISTINCT dt.CheckDate, p.Ref FROM
(
SELECT dt.CheckDate FROM
(
SELECT DATEADD(DAY, n.number, @StartDate - 1) CheckDate
FROM numbers n
) dt
) dt
INNER JOIN @Periods p
ON dt.CheckDate >= p.StartDate
AND dt.CheckDate <= p.EndDate
),
t AS
(
SELECT
dt.CheckDate d,
dt.Ref,
ROW_NUMBER() OVER(PARTITION BY Ref ORDER BY CheckDate) i
FROM dt
)
SELECT
Ref,
CAST(MIN(d) AS DATE) PeriodStart,
CAST(MAX(d) AS DATE) PeriodEnd
FROM t
GROUP BY DATEDIFF(DAY,i,d), t.Ref
这是输出:
Ref PeriodStart PeriodEnd
6931 2012-01-01 2013-04-18
6931 2013-05-01 2013-05-31
6931 2013-07-01 2013-07-11
6941 2013-04-01 2013-07-30