Wstaw brakujące daty z zapytania

9

Jak mogę wstawić brakujące daty z utworzonego przeze mnie zapytania? Wynik poniżej:

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

Chcę, aby w wyniku brakowało dat o wartości 0, jak pokazano poniżej:

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

Pamiętaj, że mam dostęp tylko do odczytu do serwera.

Arvin
źródło
czy używasz jakiegoś zapytania, aby pobrać wynik? czy masz zdefiniowany zakres dat. czy możesz dodać zapytanie lub tabelę
vijayp
1
Skorzystaj z tabeli kalendarza, wybierz jedną z nich, a następnie dołącz do swoich częstotliwości według daty social.technet.microsoft.com/wiki/contents/articles/…
Mark Sinkinson
Korzystam z zapytania, aby pobrać wynik z głównej tabeli.
Arvin
Jeśli masz dostęp tylko do odczytu , nie należy wstawiać ani aktualizować bazy danych. Zamiast tego poproś zespół DBA o pomoc.
Kin Shah,
1
@Kin Myślę, że pytanie oznacza, że ​​chcą wstawić wiersze do zestawu wyników, zamiast wstawić wiersze do rzeczywistej tabeli bazy danych.
Mark Sinkinson

Odpowiedzi:

12

Oto przykład z wykorzystaniem tabeli kalendarza (którą naprawdę powinieneś mieć). Ten przykład przedstawia tylko rok 2014, ale możesz go wypełnić dowolną liczbą lat ...

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;

Teraz zapytanie jest proste:

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);

Przykład SQLfiddle

Jeśli nie możesz utworzyć tabeli kalendarza (i nie masz pod ręką tabeli liczb), możesz po prostu wstawić ją do tabeli:

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);

Przykład SQLfiddle

Więcej informacji na temat generowania zestawów (dat, liczb itp.) Można znaleźć w tej serii:

Aaron Bertrand
źródło
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

SKRZYPCE

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
Mihai
źródło
Podejście rekurencyjne CTE staje się wykładniczo droższe w miarę poszerzania zakresu dat. Istnieją bardziej wydajne sposoby uzyskiwania zestawów do tego celu.
Aaron Bertrand
@AaronBertrand Zasięg jest tutaj dość mały, ale jakikolwiek link do alternatyw? Dla mojej ciekawości.
Mihai
1
Tak, tutaj zdarza się mały zasięg. Problem polega na tym, że ludzie uczą się tego podejścia, a następnie stosują je w znacznie większych skalach, gdzie staje się to problemem. Po co stosować powolne podejście tylko dlatego, że w tym przypadku jest „ok”? Zobacz moją odpowiedź.
Aaron Bertrand