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

在SQL中查找两个日期范围之间缺少的日期,sql,sql-server,date,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-

我有一张像这样的桌子

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 

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

         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

首先,我根据您的最小和最大日期创建了一个日历表,以获取所有相关日期。然后我把它放在你的桌子上

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

如果它们都是在午夜开始的,为什么还要麻烦存储时间组件呢?也就是说,这是应用程序代码1的工作。Mysql和ms sql server是两种具有不同sql实现的不同产品。你用哪一种?2.这里的问题通常不受欢迎,因此如果它们没有包含任何解决问题的诚实尝试,时间在这里并不重要。这就像员工从开始日期到结束日期休假的休假数据库。因此,我需要@StrawberryMy bad,Sqlserver pls@ShadowSo store dates之间缺少的日期,而不是datetimes
    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