Вставить недостающие даты из запроса


9

Как я могу вставить недостающие даты из запроса, который я создал. Результат ниже:

Date          Frequency
2014-05-18    5
2014-05-20    7
2014-05-25    7
2014-05-27    6

Я хочу, чтобы в результате отсутствовали даты со значением 0, как показано ниже:

Date          Frequency
2014-05-18    5
2014-05-19    0
2014-05-20    7
2014-05-21    0
2014-05-22    0
2014-05-23    0
2014-05-24    0
2014-05-25    7
2014-05-26    0
2014-05-27    6

Обратите внимание, что у меня есть доступ только для чтения к серверу.


Вы используете какой-либо запрос для получения результата? или у вас есть определенный диапазон дат. Вы можете добавить свой запрос или таблицу
Виджайп

1
Используйте таблицу календаря, выберите ее, а затем присоединитесь к своим частотам по дате. Social.technet.microsoft.com/wiki/contents/articles/…
Марк Синкинсон,

Я использую запрос для получения результата из основной таблицы.
Арвин

Если у вас есть доступ только для чтения, вы не должны вставлять или обновлять базу данных. Вместо этого попросите команду DBA помочь вам.
Кин Шах

1
@Kin Я думаю, что вопрос означает, что они хотят вставлять строки в набор результатов, а не вставлять строки в фактическую таблицу базы данных.
Марк Синкинсон

Ответы:


12

Вот пример использования таблицы календаря (которую вы действительно должны иметь). Этот пример просто заполняет 2014 год, но вы можете заполнить его столько лет, сколько захотите ...

CREATE TABLE dbo.Calendar(d DATE PRIMARY KEY);

INSERT dbo.Calendar(d) SELECT TOP (365)
 DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY number)-1, '20140101')
 FROM [master].dbo.spt_values
 WHERE [type] = N'P' ORDER BY number;

Теперь запрос прост:

DECLARE @s DATE = '20140518', @e DATE = '20140527';

SELECT c.d, Frequency = COALESCE(s.Frequency,0)
  FROM dbo.Calendar AS c
  LEFT OUTER JOIN dbo.splunge AS s
  ON c.d = s.[date]
  WHERE c.d >= @s
    AND c.d < DATEADD(DAY, 1, @e);

Пример SQLfiddle

Если вы не можете создать таблицу календаря (и у вас нет удобной таблицы чисел), вы можете просто вставить ее в строку:

DECLARE @s DATE = '20140518', @e DATE = '20140527';

SELECT c.d, Frequency = COALESCE(s.Frequency,0)
  FROM 
(
   SELECT TOP (DATEDIFF(DAY, @s, @e)+1)
 DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY number)-1, @s)
 FROM [master].dbo.spt_values
 WHERE [type] = N'P' ORDER BY number
) AS c(d)
  LEFT OUTER JOIN dbo.splunge2 AS s
  ON c.d = s.[date]
  WHERE c.d >= @s
    AND c.d < DATEADD(DAY, 1, @e);

Пример SQLfiddle

Для получения дополнительной информации о создании наборов (дат, чисел и т. Д.) См. Эту серию:


0
DECLARE @t TABLE(Dt Date,Frequency int)
INSERT INTO @t VALUES
('2014-05-18',5),('2014-05-20',7),('2014-05-25',7),('2014-05-27',6)



DECLARE @startDate DATE, @endDate DATE
SELECT @startDate = '2014-05-18', @endDate = '2014-05-27' --yyyy-mm-dd
;WITH Calender AS (
    SELECT @startDate AS CalanderDate
    UNION ALL
    SELECT DATEADD(day,1,CalanderDate) FROM Calender
    WHERE DATEADD(day,1,CalanderDate) <= @endDate
)
INSERT INTO @t SELECT
    Dt = CalanderDate,Frequency = 0

FROM Calender c
LEFT JOIN @t t 
ON t.Dt = c.CalanderDate
WHERE t.dt IS NULL
option (maxrecursion 0)

SELECT * FROM @t ORDER BY dt

FIDDLE

2014-05-18  5
2014-05-19  0
2014-05-20  7
2014-05-21  0
2014-05-22  0
2014-05-23  0
2014-05-24  0
2014-05-25  7
2014-05-26  0
2014-05-27  6

Рекурсивный подход CTE становится экспоненциально более дорогим, поскольку диапазон дат становится шире. Существуют более эффективные способы получения наборов для этой цели.
Аарон Бертран

@AaronBertrand Здесь диапазон довольно мал, но есть ли какие-либо ссылки на альтернативы? Для моего любопытства.
Михай

1
Да, здесь , это случается, небольшой диапазон. Проблема в том, что люди изучают этот подход, а затем применяют его в гораздо больших масштабах, где он становится проблемой. Зачем использовать медленный подход только потому, что в этом случае все нормально? Смотри мой ответ.
Аарон Бертран
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.