我需要一个 sql 查询循环,其中日期递减一天直到中断日期
I need a sql query loop with dates decrements by a day until break date
我需要一个 sql 日期按天递减的查询循环。
StartDate : 3/15/2015 [Date param] [MM/dd/yyyy]
EndDate : 3/5/2015 [Date param]
Operation : Decrement by a day toward EndDate
BreakDate : 3/10/2015 [Date param]
当前日期(在循环中)应该从开始日期到结束日期打印一天递减
如果到达中断日期,则循环应自行停止 [内部循环]
上面输入的示例结果:
3/15/2015
3/14/2015
3/13/2015
3/11/2015
3/10/2015
请帮助。
此解决方案限制为 2048 天,但可以使用不同的计数进行扩展:
SELECT cast(dateadd(day, -number, @startdate) as date) date
FROM master..spt_values
WHERE
type = 'P'
AND dateadd(day, -number, @StartDate) >= @EndDate
AND @BreakDate NOT BETWEEN dateadd(day, 1 - number, @StartDate) AND @startdate
您可以通过 WHILE
循环来完成此操作。但在循环之前,请考虑 RBAR.
这将给出预期的准确输出。
DECLARE @FromDate DATE = '3/15/2015',
@EndDate DATE = '3/5/2015',
@BreakDate DATE = '3/10/2015'
WHILE (@FromDate >= @endDate)
BEGIN
PRINT @FromDate
-- Perform your operations here
IF(@FromDate = @BreakDate)
Break;
--Incrementing to next date
SELECT @FromDate = DATEADD(DAY, -1, @FromDate)
END
GO
作业? ;)
DECLARE @dateStart SMALLDATETIME = '20150315'
DECLARE @dateEnd SMALLDATETIME = '20150305'
DECLARE @dateBreak SMALLDATETIME = '20150310'
WHILE (@dateStart>@dateEnd)
BEGIN
print @dateStart;
IF (@dateStart=@dateBreak) BREAK
SET @dateStart-=1
END
您不需要循环。你应该永远以这种心态解决SQL中的问题,这应该是最后的手段。
如果使用日期,那么最简单的解决方案是使用 calendar table,如果您没有创建一个,那么您可以使用:
DECLARE @StartDate DATE = '20150315',
@EndDate DATE = '20150305',
@BreakDate DATE = '20150310';
SELECT Date
FROM Calendar
WHERE Date <= @StartDate
AND Date > @EndDate
AND Date > @BreakDate;
不过,我很欣赏创建日历 table 并不总是一种选择,但是动态生成日期列表非常容易。来自以下文章:
- Generate a set or sequence without loops – part 1
- Generate a set or sequence without loops – part 2
- Generate a set or sequence without loops – part 3
动态执行此操作的最佳方法是使用来自常量的交叉连接(在文章中称为堆叠 CTE)。这只是从 10 行的 table 值构造函数开始,将其与自身交叉连接以获得 100 行,然后再次获得 100x100 = 10,000 行,依此类推:
DECLARE @StartDate DATE = '20150315',
@EndDate DATE = '20150305',
@BreakDate DATE = '20150310';
WITH N1 (N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
N4 (N) AS (SELECT ROW_NUMBER() OVER(ORDER BY N1.N) FROM N3 AS N1 CROSS JOIN N3 AS N2)
SELECT Date = DATEADD(DAY, 1 - N, @StartDate)
FROM N4
WHERE N <= DATEDIFF(DAY, @EndDate, @StartDate) + 1
AND N <= DATEDIFF(DAY, @BreakDate, @StartDate) + 1;
编辑
如果你的休息日期可以在开始日期之后,那么你只需要一点额外的逻辑来解决这个问题,所以你的查询变成:
DECLARE @StartDate DATE = '20150315',
@EndDate DATE = '20150305',
@BreakDate DATE = '20150310';
SELECT Date
FROM Calendar
WHERE Date <= @StartDate
AND Date > @EndDate
AND ( Date > @BreakDate
OR @BreakDate >= @StartDate
);
或
DECLARE @StartDate DATE = '20150315',
@EndDate DATE = '20150305',
@BreakDate DATE = '20150320';
WITH N1 (N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
N4 (N) AS (SELECT ROW_NUMBER() OVER(ORDER BY N1.N) FROM N3 AS N1 CROSS JOIN N3 AS N2)
SELECT Date = DATEADD(DAY, 1 - N, @StartDate)
FROM N4
WHERE N <= DATEDIFF(DAY, @EndDate, @StartDate) + 1
AND ( N <= DATEDIFF(DAY, @BreakDate, @StartDate) + 1
OR @BreakDate >= @StartDate
);
我需要一个 sql 日期按天递减的查询循环。
StartDate : 3/15/2015 [Date param] [MM/dd/yyyy]
EndDate : 3/5/2015 [Date param]
Operation : Decrement by a day toward EndDate
BreakDate : 3/10/2015 [Date param]
当前日期(在循环中)应该从开始日期到结束日期打印一天递减
如果到达中断日期,则循环应自行停止 [内部循环]
上面输入的示例结果:
3/15/2015
3/14/2015
3/13/2015
3/11/2015
3/10/2015
请帮助。
此解决方案限制为 2048 天,但可以使用不同的计数进行扩展:
SELECT cast(dateadd(day, -number, @startdate) as date) date
FROM master..spt_values
WHERE
type = 'P'
AND dateadd(day, -number, @StartDate) >= @EndDate
AND @BreakDate NOT BETWEEN dateadd(day, 1 - number, @StartDate) AND @startdate
您可以通过 WHILE
循环来完成此操作。但在循环之前,请考虑 RBAR.
这将给出预期的准确输出。
DECLARE @FromDate DATE = '3/15/2015',
@EndDate DATE = '3/5/2015',
@BreakDate DATE = '3/10/2015'
WHILE (@FromDate >= @endDate)
BEGIN
PRINT @FromDate
-- Perform your operations here
IF(@FromDate = @BreakDate)
Break;
--Incrementing to next date
SELECT @FromDate = DATEADD(DAY, -1, @FromDate)
END
GO
作业? ;)
DECLARE @dateStart SMALLDATETIME = '20150315'
DECLARE @dateEnd SMALLDATETIME = '20150305'
DECLARE @dateBreak SMALLDATETIME = '20150310'
WHILE (@dateStart>@dateEnd)
BEGIN
print @dateStart;
IF (@dateStart=@dateBreak) BREAK
SET @dateStart-=1
END
您不需要循环。你应该永远以这种心态解决SQL中的问题,这应该是最后的手段。
如果使用日期,那么最简单的解决方案是使用 calendar table,如果您没有创建一个,那么您可以使用:
DECLARE @StartDate DATE = '20150315',
@EndDate DATE = '20150305',
@BreakDate DATE = '20150310';
SELECT Date
FROM Calendar
WHERE Date <= @StartDate
AND Date > @EndDate
AND Date > @BreakDate;
不过,我很欣赏创建日历 table 并不总是一种选择,但是动态生成日期列表非常容易。来自以下文章:
- Generate a set or sequence without loops – part 1
- Generate a set or sequence without loops – part 2
- Generate a set or sequence without loops – part 3
动态执行此操作的最佳方法是使用来自常量的交叉连接(在文章中称为堆叠 CTE)。这只是从 10 行的 table 值构造函数开始,将其与自身交叉连接以获得 100 行,然后再次获得 100x100 = 10,000 行,依此类推:
DECLARE @StartDate DATE = '20150315',
@EndDate DATE = '20150305',
@BreakDate DATE = '20150310';
WITH N1 (N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
N4 (N) AS (SELECT ROW_NUMBER() OVER(ORDER BY N1.N) FROM N3 AS N1 CROSS JOIN N3 AS N2)
SELECT Date = DATEADD(DAY, 1 - N, @StartDate)
FROM N4
WHERE N <= DATEDIFF(DAY, @EndDate, @StartDate) + 1
AND N <= DATEDIFF(DAY, @BreakDate, @StartDate) + 1;
编辑
如果你的休息日期可以在开始日期之后,那么你只需要一点额外的逻辑来解决这个问题,所以你的查询变成:
DECLARE @StartDate DATE = '20150315',
@EndDate DATE = '20150305',
@BreakDate DATE = '20150310';
SELECT Date
FROM Calendar
WHERE Date <= @StartDate
AND Date > @EndDate
AND ( Date > @BreakDate
OR @BreakDate >= @StartDate
);
或
DECLARE @StartDate DATE = '20150315',
@EndDate DATE = '20150305',
@BreakDate DATE = '20150320';
WITH N1 (N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
N4 (N) AS (SELECT ROW_NUMBER() OVER(ORDER BY N1.N) FROM N3 AS N1 CROSS JOIN N3 AS N2)
SELECT Date = DATEADD(DAY, 1 - N, @StartDate)
FROM N4
WHERE N <= DATEDIFF(DAY, @EndDate, @StartDate) + 1
AND ( N <= DATEDIFF(DAY, @BreakDate, @StartDate) + 1
OR @BreakDate >= @StartDate
);