Там может быть более простой способ сделать это, но часто при попытке найти недостающие номера/даты вам нужно создать эти цифры/даты затем LEFT JOIN
в существующий данных, чтобы найти то, что отсутствует. Вы можете создать даты в вопросе с рекурсивным КТР:
WITH cal AS (SELECT CAST('2014-07-01' AS DATE) dt
UNION ALL
SELECT DATEADD(DAY,1,dt)
FROM cal
WHERE dt < '2014-07-30')
SELECT *
FROM cal
Затем вы LEFT JOIN
к столу, чтобы получить список отсутствующих дат:
WITH cal AS (SELECT CAST('2014-07-01' AS DATE) dt
UNION ALL
SELECT DATEADD(DAY,1,dt)
FROM cal
WHERE dt < '2014-07-30')
SELECT DISTINCT cal.dt
FROM cal
LEFT JOIN YourTable a
ON cal.dt BETWEEN CAST(SS_StartDate AS DATE) AND CAST(SS_EndDate AS DATE)
WHERE a.SS_StartDate IS NULL
Тогда вам необходимо выяснить, является ли или нет последовательные строки принадлежат в том же диапазоне, или если они имеют зазор между ними, используя DATEDIFF()
и ROW_NUMBER()
:
WITH cal AS (SELECT CAST('2014-07-01' AS DATE) dt
UNION ALL
SELECT DATEADD(DAY,1,dt)
FROM cal
WHERE dt < '2014-07-30')
,dt_list AS (SELECT DISTINCT cal.dt
FROM cal
LEFT JOIN YourTable a
ON cal.dt BETWEEN CAST(SS_StartDate AS DATE) AND CAST(SS_EndDate AS DATE)
WHERE a.SS_StartDate IS NULL)
SELECT dt
,DATEDIFF(D, ROW_NUMBER() OVER(ORDER BY dt), dt) AS dt_range
FROM dt_list
Затем с помощью MIN()
и MAX()
получить диапазоны:
WITH cal AS (SELECT CAST('2014-07-01' AS DATE) dt
UNION ALL
SELECT DATEADD(DAY,1,dt)
FROM cal
WHERE dt < '2014-07-30')
,dt_list AS (SELECT DISTINCT cal.dt
FROM cal
LEFT JOIN YourTable a
ON cal.dt BETWEEN CAST(SS_StartDate AS DATE) AND CAST(SS_EndDate AS DATE)
WHERE a.SS_StartDate IS NULL)
,dt_range AS (SELECT dt
,DATEDIFF(D, ROW_NUMBER() OVER(ORDER BY dt), dt) AS dt_range
FROM dt_list)
SELECT MIN(dt) AS BeginRange
,MAX(dt) AS EndRange
FROM dt_range
GROUP BY dt_range;
--OPTION (MAXRECURSION 0)
Демо: SQL Fiddle
Примечание: Если диапазон вы проверяете более чем 100 дней вам необходимо указать MAXRECURSION
, 0 означает, что нет предела.
Примечание2: Если ваши SE
дат предназначены для привода полного диапазона дат, а затем изменить cal
КТР с фиксированных дат для запросов с использованием MIN()
и MAX()
соответственно.
Я попытался с помощью зрения и используя время цикла, но не мог получить всю логику. – GPK
Аналогичный вопрос: [SQL Query, чтобы показать пробелы между несколькими диапазонами дат] (https://stackoverflow.com/questions/9604400/sql-query-to-show-gaps-between-multiple-date-ranges) – Anssssss
Может ли SS_StartDate быть раньше se_startdate или SS_EndDate будет позже se_enddate? Другими словами - интервал (se_startdate, se_enddate) всегда включает интервал (SS_StartDate, SS_EndDate)? – Alexander