Inserir datas ausentes de uma consulta

9

Como posso inserir datas ausentes de uma consulta que eu criei. O resultado abaixo:

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

Quero que o resultado tenha datas ausentes com o valor 0, como mostrado abaixo:

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

Observe que eu tenho acesso somente de leitura ao servidor.

Arvin
fonte
você está usando alguma consulta para buscar o resultado? ou você tem um período definido. você pode adicionar sua consulta ou tabela
vijayp
11
Use uma tabela de calendário, selecione com isso e, em seguida, juntar-se aos seus frequências por data social.technet.microsoft.com/wiki/contents/articles/...
Mark Sinkinson
Estou usando a consulta para buscar o resultado da tabela principal.
Arvin
Se você tiver acesso somente leitura , não deverá inserir ou atualizar o banco de dados. Em vez disso, peça à sua equipe do DBA para ajudá-lo.
Kin Shah
11
@ Kin Acho que a pergunta significa que eles querem inserir linhas no conjunto de resultados, em vez de inserir linhas em uma tabela de banco de dados real.
Mark Sinkinson

Respostas:

12

Aqui está um exemplo usando uma tabela de calendário (que você realmente deveria ter). Este exemplo apenas preenche 2014, mas você pode preenchê-lo com quantos anos quiser ...

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;

Agora a consulta é simples:

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

Exemplo de SQLfiddle

Se você não pode criar uma tabela de calendário (e também não possui uma tabela de números), basta colocá-la em linha:

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

Exemplo de SQLfiddle

Para saber mais sobre a geração de conjuntos (de datas, números etc.), consulte esta série:

Aaron Bertrand
fonte
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
Mihai
fonte
A abordagem CTE recursiva fica exponencialmente mais cara à medida que o período aumenta. Existem maneiras mais eficientes de derivar conjuntos para esse fim.
Aaron Bertrand
@AaronBertrand O alcance é bem pequeno aqui, mas qualquer link para alternativas? Para minha curiosidade.
Mihai
11
Sim, aqui , acontece que é um pequeno intervalo. O problema é que as pessoas aprendem essa abordagem e a aplicam em escalas muito maiores, onde ela se torna um problema. Por que usar uma abordagem lenta apenas porque está "ok" neste caso? Veja minha resposta.
Aaron Bertrand