Insertar fechas faltantes de una consulta

9

¿Cómo puedo insertar fechas faltantes de una consulta que creé? El resultado a continuación:

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

Quiero que el resultado tenga fechas faltantes con valor 0 como se muestra a continuación:

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

Tenga en cuenta que tengo acceso de solo lectura al servidor.

Arvin
fuente
¿Está utilizando alguna consulta para obtener el resultado? o tiene un rango de fechas definido. puede agregar su consulta o tabla
vijayp
1
Use una tabla de calendario, seleccione de eso y luego únase a sus frecuencias por fecha social.technet.microsoft.com/wiki/contents/articles/…
Mark Sinkinson
Estoy usando la consulta para obtener el resultado de la tabla principal.
Arvin
Si tiene acceso de solo lectura , no se supone que inserte o actualice la base de datos. En cambio, pídale a su equipo de DBA que lo ayude.
Kin Shah
1
@Kin Creo que la pregunta significa que quieren insertar filas en el conjunto de resultados, en lugar de insertar filas en una tabla de base de datos real.
Mark Sinkinson

Respuestas:

12

Aquí hay un ejemplo usando una tabla de calendario (que realmente debería tener). Este ejemplo solo contiene 2014, pero puedes rellenarlo tantos años como quieras ...

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;

Ahora la consulta es simple:

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

Ejemplo de SQLfiddle

Si no puede crear una tabla de calendario (y tampoco tiene una tabla de números a mano), puede ponerla en línea:

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

Ejemplo de SQLfiddle

Para más información sobre conjuntos generadores (de fechas, números, etc.) vea esta serie:

Aaron Bertrand
fuente
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

VIOLÍN

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
fuente
El enfoque recursivo de CTE se vuelve exponencialmente más caro a medida que se amplía el rango de fechas. Hay formas más eficientes de derivar conjuntos para este propósito.
Aaron Bertrand
@AaronBertrand El rango es bastante pequeño aquí, pero ¿hay algún enlace a alternativas? Para mi curiosidad.
Mihai
1
Sí, aquí , resulta ser un rango pequeño. El problema es que las personas aprenden este enfoque y luego lo aplican en escalas mucho más grandes donde se convierte en un problema. ¿Por qué utilizar un enfoque lento solo porque está "bien" en este caso? Mira mi respuesta.
Aaron Bertrand