Minggu lalu salah satu rekan saya meminta saya untuk membantunya menulis kueri untuk mengisi tanggal yang hilang dalam keluaran kueri. Saya menemukan beberapa solusi, sepertinya tidak ada yang nyaman bagi saya. Jadi, saya mengkompilasi sendiri menggunakan CTE rekursif atau Common Table Expression.
Pernyataan Masalah
Katakanlah kita memiliki tabel yang berisi catatan panggilan masuk dari layanan pelanggan dari 1 hingga 10 Juni 2021. Dalam beberapa hari, tidak ada catatan panggilan. Jika kita menjalankan pernyataan GROUP BY pada kolom datetime, beberapa hari akan hilang. Output yang diinginkan adalah, tanggal yang hilang akan bernilai 0. Contoh keluaran akan di bawah ini:
Permintaan
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)
Contoh Keluaran
Keluaran yang Diinginkan
Pendekatan Saya terhadap Solusi
Daripada menggunakan kueri GROUP BY sederhana, CTE dan SUB QUERY digunakan. CTE rekursif digunakan untuk menghasilkan rentang tanggal dan LEFT OUTER JOIN digunakan untuk menggabungkan nilai dengan tanggal. Mari kita jelaskan langkah demi langkah.
CTE/Ekspresi Tabel Umum
CTE atau Common Table Expression menentukan kumpulan hasil bernama sementara yang diturunkan dari kueri sederhana dan didefinisikan dalam lingkup eksekusi pernyataan SELECT/INSERT/UPDATE/DELETE/MERGE/CREATE VIEW tunggal. Itu bisa merujuk ke dirinya sendiri juga yang disebut CTE rekursif.
Menyiapkan Data
-- 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')
Buat Kueri
Pertama, kita akan menulis CTE yang akan menghasilkan semua tanggal dalam rentang tanggal tersebut.
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;
Sekarang CTE ini akan di refactored untuk membuat sub query dengan LEFT OUTER JOIN sehingga muncul tanggal yang tidak memiliki nilai dan mengandung nilai 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
Hasil Akhir
Kesimpulan
Harapan, itu akan membantu Anda. Selamat TSQL!
Ini juga tersedia di blog pribadi saya!