sql >> Base de Datos >  >> RDS >> Sqlserver

Complete las fechas que faltan para la salida de consultas de SQL Server usando CTE

La semana pasada, uno de mis colegas me pidió que lo ayudara a escribir una consulta para completar las fechas que faltan en el resultado de la consulta. Encontré un par de soluciones, ninguna me pareció conveniente. Por lo tanto, compilé el mío usando CTE recursivo o expresión de tabla común.

Enunciado del problema

Digamos que tenemos una tabla que contiene registros de llamadas entrantes de atención al cliente del 1 al 10 de junio de 2021. En algunos días, no hay registro de llamadas. Si ejecutamos la instrucción GROUP BY en la columna de fecha y hora, faltarán algunos días. El resultado deseado es que las fechas faltantes tendrán un valor de 0. El resultado de muestra será el siguiente:

Consulta

SELECT CONVERT(varchar(10),B.call_time,111) AS OriginalDate, COUNT(*) as total
FROM Test1 B
GROUP BY CONVERT(varchar(10),B.call_time,111)
ORDER BY CONVERT(varchar(10),B.call_time,111)

Salida de muestra

Salida deseada

Mi enfoque hacia la solución

En lugar de utilizar una consulta GROUP BY simple, se utilizan CTE y SUB QUERY. El CTE recursivo se usa para generar el intervalo de fechas y la UNIÓN EXTERNA IZQUIERDA se usa para combinar el valor con la fecha. Expliquemos paso a paso.

CTE/Expresión de tabla común

CTE o Expresión de tabla común especifica un conjunto de resultados con nombre temporal que se deriva de una consulta simple y se define dentro del ámbito de ejecución de una sola instrucción SELECT/INSERT/UPDATE/DELETE/MERGE/CREATE VIEW. También puede referirse a sí mismo, lo que se denomina CTE recursivo.

Preparación de datos

-- Create the table
CREATE TABLE Test1(
call_time datetime,
name    varchar(10) default ('Mehedi')
)
GO
-- Populate with sample data
INSERT INTO Test1 (call_time, name)
VALUES ('2021-06-01 08:00','A')
,('2021-06-01 09:05','C')
,('2021-06-01 12:50','E')
,('2021-06-01 16:17','D')
,('2021-06-01 18:53','G')
,('2021-06-03 11:07','F')
,('2021-06-03 13:09','A')
,('2021-06-03 16:26','E')
,('2021-06-03 19:56','C')
,('2021-06-03 21:24','A')
,('2021-06-04 19:13','A')
,('2021-06-04 11:45','B')
,('2021-06-04 15:02','C')
,('2021-06-08 23:02','A')
,('2021-06-09 03:04','E')

Crear la consulta

Primero, escribiremos un CTE que generará todas las fechas dentro del rango de fechas.

DECLARE @StartDate DATE, @EndDate DATE
SET @StartDate = '2021-11-01'
SET @EndDate = '2021-11-08'
;WITH cte AS
(    SELECT @StartDate AS sDate
UNION ALL
SELECT DATEADD(DAY,1,sDate)
FROM cte
WHERE sDate < @EndDate
)
SELECT  sDate
FROM cte;

Ahora este CTE se refactorizará para hacer una subconsulta con LEFT OUTER JOIN para que la fecha que no tiene el valor aparezca y contenga el valor 0.

DECLARE @startdate DATETIME = '2021-06-01'
DECLARE @endDate DATETIME = '2021-06-10'
;WITH cte
AS
(
SELECT @startdate as sDate
UNION All
SELECT DATEADD(day,1,sDate) From cte where DATEADD(day,1,sDate) <= @endDate
)
SELECT
C.OriginalDate
,C.total
FROM
(
SELECT CONVERT(varchar(10),A.sDate,111) AS OriginalDate, COUNT(B.call_time) as total
FROM cte A
LEFT OUTER JOIN Test1 B
ON A.sDate = CONVERT(varchar(10),B.call_time,111)
GROUP by CONVERT(varchar(10),A.sDate,111)
) C
ORDER BY C.OriginalDate

Resultado final

Conclusión

Esperamos que sea útil para usted. ¡Feliz TSQLing!

¡También está disponible en mi blog personal!