SQL 查询以检查两个日期之间是否不存在日期

SQL Query to check if a date doesn't exist between two dates

我使用一个包含几天日程表的数据库。

我请求查找可能的错误。

我想要一个检查日期的查询。如果期间的某一天 (startDate / endDate) 丢失,我想知道。

例如,如果我在数据库中的列 "Day" 包含:

01/01/2019
01/02/2019
01/04/2019

是否可以进行如下查询:

SELECT Day FROM Schedule WHERE Day doesn't exist BETWEEN 01/01/2019 AND 01/04/2019 

我想 return 给我 01/03/2019。

是的,这是可能的(使用日历 table 或临时查询来生成它):

WITH cte AS (
  SELECT CAST('20190101' AS DATETIME) t
  UNION ALL
  SELECT t + 1 AS t
  FROM cte
  WHERE t < '20190104'
)
SELECT c.*
FROM cte c
LEFT JOIN Schedule s
  ON c.t = s.[day]
WHERE s.[day] IS NULL;

db<>fiddle demo

我的第一个建议是使用您的 calendar table,如果您没有,请创建一个。它们非常有用。您的查询就这么简单:

-- DUMMY DATA
WITH Schedule (Day) AS (SELECT CONVERT(DATE, D) FROM (VALUES ('20190101'), ('20190102'), ('20190104')) x (D))

SELECT  Date
FROM    dbo.Calendar AS c
WHERE   c.Date >= '20190101'        -- ADD A START DATE THAT SUITS YOUR NEEDS
AND     c.Date < '20190105'         -- ADD AN END DATE THAT SUITS YOUR NEEDS
AND     NOT EXISTS
        (   SELECT  1
            FROM    Schedule AS s
            WHERE   s.Day = c.Date
        );

如果您不想或不能创建日历table,您仍然可以非常轻松地即时执行此操作:

DECLARE @StartDate DATE = '2019-01-01',
        @EndDate DATE = GETDATE();

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),
Dates AS
(   SELECT TOP (DATEDIFF(DAY, @StartDate, @EndDate) + 1)
            Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY N) - 1, @StartDate)
    FROM N3
)
SELECT  *
FROM    Dates;

这将简单地生成给定日期范围内所有日期的列表。如需进一步阅读,请参阅:

然后您只需要排除该日期存在时间表的行:

DECLARE @StartDate DATE = '20190101',
        @EndDate DATE = '20190105';

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),
Dates AS
(   SELECT TOP (DATEDIFF(DAY, @StartDate, @EndDate) + 1)
            Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY N) - 1, @StartDate)
    FROM N3
),
-- DUMMY DATA
Schedule (Day) AS (SELECT CONVERT(DATE, D) FROM (VALUES ('20190101'), ('20190102'), ('20190104')) x (D))

SELECT  *
FROM    Dates AS d
WHERE   NOT EXISTS
        (   SELECT  1
            FROM    Schedule AS s
            WHERE   s.Day = d.Date
        );

输出

Date
----------
2019-01-03
2019-01-05

我会做以下事情:

1.- 获取两个日期之间的天数:

 Set @numberofdays = DATEDIFF(DAY, @StartDate, @EndDate)

2.- 获取数据库中这些日期之间的天数并进行比较

if @numberofdays == (select count(distinct(day)) from schedule where days>=@Startdate and days<=@EndDate)
print N'ok'
else
print N'days are missing' 

这是为了防止您只想知道是否缺少日期,如果您确实需要知道哪些是您可以做的

else  
set @currentday = @StartDate
while @currentday < @EndDate
begin
if (select day from schedule where day=@currentday == null)
print @currentday
DATEADD(day, 1, @currentday)
end