我需要一个 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 并不总是一种选择,但是动态生成日期列表非常容易。来自以下文章:

动态执行此操作的最佳方法是使用来自常量的交叉连接(在文章中称为堆叠 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
    );