Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Uzupełnij brakujące daty dla wyniku zapytania SQL Server za pomocą CTE

W zeszłym tygodniu jeden z moich kolegów poprosił mnie o pomoc w napisaniu zapytania w celu uzupełnienia brakujących dat w wynikach zapytania. Natknąłem się na kilka rozwiązań, żadne nie wydawało mi się wygodne. Skompilowałem więc własne, używając rekurencyjnego CTE lub Common Table Expression.

Oświadczenie o problemie

Załóżmy, że mamy tabelę, która zawiera zapisy rozmów przychodzących do obsługi klienta od 1 do 10 czerwca 2021 r. W niektóre dni nie ma rejestru rozmów. Jeśli uruchomimy instrukcję GROUP BY w kolumnie datetime, będzie brakować kilku dni. Pożądanym wyjściem jest, że brakujące daty będą miały wartość 0. Przykładowe dane wyjściowe będą poniżej:

Zapytanie

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)

Przykładowe wyjście

Pożądane wyjście

Moje podejście do rozwiązania

Zamiast używać prostego zapytania GROUP BY, używane są CTE i SUB QUERY. Rekursywne CTE jest używane do generowania zakresu dat, a LEFT OUTER JOIN jest używane do łączenia wartości z datą. Wyjaśnijmy krok po kroku.

CTE/wspólne wyrażenie tabelowe

CTE lub Common Table Expression określa tymczasowy nazwany zestaw wyników, który pochodzi z prostego zapytania i jest zdefiniowany w zakresie wykonywania pojedynczej instrukcji SELECT/INSERT/UPDATE/DELETE/MERGE/CREATE VIEW. Może odnosić się również do siebie, co nazywa się rekursywnym CTE.

Przygotowywanie danych

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

Zbuduj zapytanie

Najpierw napiszemy CTE, które wygeneruje wszystkie daty w zakresie dat.

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;

Teraz to CTE zostanie zrefaktoryzowane, aby utworzyć podzapytanie z LEFT OUTER JOIN, tak aby pojawiła się data, która nie ma tej wartości i zawiera wartość 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

Końcowe wyjście

Wniosek

Mam nadzieję, że będzie to dla ciebie pomocne. Miłego TSQLingu!

Jest również dostępny na moim osobistym blogu!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Utwórz bazę danych w SQL Server 2017

  2. W tabeli odniesienia nie ma kluczy podstawowych ani kandydujących, które pasują do listy kolumn odniesienia w kluczu obcym

  3. Optymalny sposób łączenia/agregowania ciągów

  4. Jak włączyć ograniczenie wyboru w programie SQL Server (przykład T-SQL)

  5. Planowe utrzymanie bazy danych IS 24/7 w MS SQL Server