在SQL中查找两个日期范围之间的缺少日期

时间:2017-08-24 05:12:21

标签: sql sql-server date

我有一张像

这样的表格
ID      StartDate                EndDate   
AAA     2017-03-17 00:00:00.000  2017-03-19 00:00:00.000  
BB      2017-06-20 00:00:00.000  2017-06-25 00:00:00.000    
CC      2017-05-13 00:00:00.000  2017-05-17 00:00:00.000  
DD      2017-06-20 00:00:00.000  2017-05-27 00:00:00.000  
EE      2017-03-01 00:00:00.000  2017-03-05 00:00:00.000  
FF      2017-08-07 00:00:00.000  2017-08-11 00:00:00.000

我需要在这些范围之间缺少日期,输出表应该像

ID    Date  
AAA   2017-03-17 00:00:00.000  -- Start date for AAA   
AAA   2017-03-18 00:00:00.000  
AAA   2017-03-19 00:00:00.000  -- End date for AAA  
BB    2017-06-20 00:00:00.000  -- start date for BB  
BB    2017-06-21 00:00:00.000  
BB    2017-06-22 00:00:00.000  
BB    2017-06-23 00:00:00.000  
BB    2017-06-24 00:00:00.000  
BB    2017-06-25 00:00:00.000  -- End date for BB 

3 个答案:

答案 0 :(得分:0)

您需要添加循环以获取开始日期和结束日期之间的日期,例如:

         DECLARE  @table table (ID Varchar(50), StartDate datetime,EndDate datetime)

            insert into @table values ('AAA','2017-03-17 00:00:00.000',' 2017-03-19 00:00:00.000')
            insert into @table values ('BB','2017-06-20 00:00:00.000 ',' 2017-06-25 00:00:00.000')
            insert into @table values ('CC','2017-05-13 00:00:00.000 ',' 2017-05-17 00:00:00.000')
            insert into @table values ('DD','2017-06-20 00:00:00.000 ',' 2017-05-27 00:00:00.000')
            insert into @table values ('EE','2017-03-01 00:00:00.000 ',' 2017-03-05 00:00:00.000')
            insert into @table values ('FF','2017-08-07 00:00:00.000 ',' 2017-08-11 00:00:00.000')


            SELECT * FROM @table

            SELECT id, StartDate FROM @table WHERE id='AAA'  
            union all 
            SELECT id, Dateadd(day,1,startdate) AS date FROM @table WHERE id='AAA'  AND Dateadd(day,1,startdate)<EndDate
            union all 
            SELECT id, EndDate FROM @table WHERE id='AAA'  
            union all 

            SELECT id, StartDate FROM @table WHERE id='BB'  
            union all 
            SELECT id, Dateadd(day,1,startdate) AS date FROM @table WHERE id='BB'  AND Dateadd(day,1,startdate)<EndDate
            union all 
            SELECT id, EndDate FROM @table WHERE id='BB'  
            union all 

            SELECT id, StartDate FROM @table WHERE id='CC'  
            union all 
            SELECT id, Dateadd(day,1,startdate) AS date FROM @table WHERE id='CC'  AND Dateadd(day,1,startdate)<EndDate
            union all 
            SELECT id, EndDate FROM @table WHERE id='CC'  
            union all 

            SELECT id, StartDate FROM @table WHERE id='DD'  
            union all 
            SELECT id, Dateadd(day,1,startdate) AS date FROM @table WHERE id='DD'  AND Dateadd(day,1,startdate)<EndDate
            union all 
            SELECT id, EndDate FROM @table WHERE id='DD'  
            union all 


            SELECT id, StartDate FROM @table WHERE id='EE'  
            union all 
            SELECT id, Dateadd(day,1,startdate) AS date FROM @table WHERE id='EE'  AND Dateadd(day,1,startdate)<EndDate
            union all 
            SELECT id, EndDate FROM @table WHERE id='EE'  
            union all 


            SELECT id, StartDate FROM @table WHERE id='FF'  
            union all 
            SELECT id, Dateadd(day,1,startdate) AS date FROM @table WHERE id='FF'  AND Dateadd(day,1,startdate)<EndDate
            union all 
            SELECT id, EndDate FROM @table WHERE id='FF'  

        Output:
             id StartDate
            AAA 2017-03-17 00:00:00.000
            AAA 2017-03-18 00:00:00.000
            AAA 2017-03-19 00:00:00.000
            BB  2017-06-20 00:00:00.000
            BB  2017-06-21 00:00:00.000
            BB  2017-06-25 00:00:00.000
            CC  2017-05-13 00:00:00.000
            CC  2017-05-14 00:00:00.000
            CC  2017-05-17 00:00:00.000
            DD  2017-06-20 00:00:00.000
            DD  2017-05-27 00:00:00.000
            EE  2017-03-01 00:00:00.000
            EE  2017-03-02 00:00:00.000
            EE  2017-03-05 00:00:00.000
            FF  2017-08-07 00:00:00.000
            FF  2017-08-08 00:00:00.000
            FF  2017-08-11 00:00:00.000

答案 1 :(得分:0)

首先,我根据您的MIN和MAX日期创建了一个日历表,以获取所涉及的所有日期。然后我把它加到你的桌子上。

DECLARE @calendar AS TABLE ([Date] DATETIME)

DECLARE @maxDate AS DATETIME = (SELECT CASE WHEN MAX(StartDate) > MAX(EndDate) 
                                        THEN MAX(StartDate) 
                                        ELSE MAX(EndDate) 
                                   END FROM @YourTable)

DECLARE @minDate AS DATETIME = (SELECT CASE WHEN MIN(StartDate) < MIN(EndDate) 
                                        THEN MIN(StartDate)
                                        ELSE MIN(EndDate) 
                                    END FROM @YourTable)

WHILE (@minDate < @maxDate)
BEGIN
    INSERT INTO @calendar 
    VALUES (@minDate)
    SET @minDate = DATEADD(DAY, 1, @minDate)
END

SELECT [Id], a.[Date]
FROM (Select [Date] FROM @calendar) a
LEFT JOIN @YourTable ON [Date] BETWEEN [StartDate] AND [EndDate]
WHERE [Id] IS NOT NULL

enter image description here

答案 2 :(得分:0)

    CREATE TABLE t
    (
      ID NVARCHAR(5) NOT NULL ,
      StartDate DATETIME NOT NULL ,
      EndDate DATETIME NOT NULL
    );
    GO

INSERT  INTO dbo.t
        ( ID, StartDate, EndDate )
VALUES  ( N'AAA', '2017-03-17 00:00:00.000', '2017-03-19 00:00:00.000' ),
        ( N'BB', '2017-06-20 00:00:00.000', '2017-06-25 00:00:00.000' ),
        ( N'CC', '2017-05-13 00:00:00.000', '2017-05-17 00:00:00.000' ),
        ( N'DD', '2017-06-20 00:00:00.000', '2017-05-27 00:00:00.000' ),
        ( N'EE', '2017-03-01 00:00:00.000', '2017-03-05 00:00:00.000' ),
        ( N'FF', '2017-08-07 00:00:00.000', '2017-08-11 00:00:00.000' );



WITH    cte
          AS ( SELECT   ID ,
                        StartDate
               FROM     dbo.t
               UNION ALL
               SELECT   cte.ID ,
                        DATEADD(DAY, 1, cte.StartDate)
               FROM     cte
                        INNER JOIN dbo.t ON t.ID = cte.ID
               WHERE    cte.StartDate < EndDate
             )
    SELECT  cte.ID ,
            cte.StartDate
    FROM    cte
    ORDER BY cte.ID ,
            cte.StartDate;

结果:

ID    StartDate
----- -----------------------
AAA   2017-03-17 00:00:00.000
AAA   2017-03-18 00:00:00.000
AAA   2017-03-19 00:00:00.000
BB    2017-06-20 00:00:00.000
BB    2017-06-21 00:00:00.000
BB    2017-06-22 00:00:00.000
BB    2017-06-23 00:00:00.000
BB    2017-06-24 00:00:00.000
BB    2017-06-25 00:00:00.000
CC    2017-05-13 00:00:00.000
CC    2017-05-14 00:00:00.000
CC    2017-05-15 00:00:00.000
CC    2017-05-16 00:00:00.000
CC    2017-05-17 00:00:00.000
DD    2017-06-20 00:00:00.000
EE    2017-03-01 00:00:00.000
EE    2017-03-02 00:00:00.000
EE    2017-03-03 00:00:00.000
EE    2017-03-04 00:00:00.000
EE    2017-03-05 00:00:00.000
FF    2017-08-07 00:00:00.000
FF    2017-08-08 00:00:00.000
FF    2017-08-09 00:00:00.000
FF    2017-08-10 00:00:00.000
FF    2017-08-11 00:00:00.000