Generate Deret Tanggal di SQL
TL;DR
Generate deret tanggal di SQL bikin satu kolom berisi tanggal berurutan tanpa perlu tabel sumber. Di PostgreSQL caranya pakai generate_series, sedangkan di MySQL dan SQL Server pakai recursive CTE yang nambah satu hari tiap putaran. Deret tanggal ini kepakai buat ngisi hari yang kosong di laporan, supaya hari tanpa transaksi tetap muncul dengan nilai nol, bukan hilang dari hasil.
Generate deret tanggal di SQL bikin satu kolom berisi tanggal berurutan tanpa perlu tabel sumber. Satu teknik buat ngisi hari yang kosong di laporan, biar hari tanpa transaksi tetap kelihatan.
Ini masalah klasik. Kamu GROUP BY tanggal dari tabel penjualan, lalu bikin grafik tren harian. Tapi hari yang nggak ada transaksinya hilang dari hasil, dan grafiknya jadi bolong seakan hari itu nggak pernah ada.
Rata-rata harian juga jadi salah. Kalau 4 hari sepi nggak keitung, rata-ratamu ketarik naik. Deret tanggal yang benerin ini.
Kenapa perlu generate deret tanggal di SQL?
Tabel transaksi cuma nyimpen hari yang ada penjualannya. Hari sepi nggak punya baris sama sekali. Waktu di-GROUP BY, hari itu ilang, bukan muncul sebagai nol. Deret tanggal ngasih daftar hari lengkap sebagai kerangka, lalu data transaksi ditempel di atasnya lewat LEFT JOIN.
Hasilnya laporan yang jujur. Hari sepi tetap muncul dengan angka nol, dan itu justru informasi penting buat lihat pola. Teknik ini pondasi buat semua analisa time series yang butuh sumbu waktu rapat.
Gimana cara generate deret tanggal di PostgreSQL?
PostgreSQL punya fungsi bawaan paling ringkas: generate_series. Kasih tanggal awal, tanggal akhir, dan interval, dia ngasih satu baris per langkah.
SELECT gs::date AS tanggal
FROM generate_series(
'2026-01-01'::date,
'2026-01-31'::date,
'1 day'::interval
) AS gs;
Query ini ngasih 31 baris, satu buat tiap hari di Januari 2026. Bagian ::date ngubah hasilnya dari timestamp jadi tanggal murni.
Ganti intervalnya buat deret lain:
| Kebutuhan | interval |
|---|---|
| Deret harian | '1 day' |
| Deret mingguan | '1 week' |
| Deret bulanan | '1 month' |
| Tiap 15 menit (untuk jam) | '15 minutes' |
Gimana cara generate deret tanggal di MySQL dan SQL Server?
MySQL dan SQL Server nggak punya generate_series buat tanggal. Gantinya, pakai recursive CTE yang nambah satu hari tiap putaran sampai sampai batas.
WITH RECURSIVE deret AS (
SELECT DATE('2026-01-01') AS tanggal
UNION ALL
SELECT tanggal + INTERVAL 1 DAY
FROM deret
WHERE tanggal < '2026-01-31'
)
SELECT tanggal FROM deret;
Cara bacanya: anchor mulai dari 1 Januari. Tiap putaran nambah sehari, dan berhenti begitu nyampe 31 Januari. Di SQL Server, ganti DATE('2026-01-01') jadi CAST('2026-01-01' AS date) dan + INTERVAL 1 DAY jadi DATEADD(day, 1, tanggal).
Catatan buat MySQL: batas kedalaman recursive defaultnya 1000. Buat deret lebih dari 1000 hari, naikin dulu cte_max_recursion_depth.
Gimana cara isi tanggal kosong di laporan penjualan?
Ini alasan utama orang butuh deret tanggal. Gabungin deret dengan data transaksi pakai LEFT JOIN, lalu COALESCE biar yang kosong jadi nol.
WITH deret AS (
SELECT gs::date AS tanggal
FROM generate_series('2026-01-01'::date, '2026-01-31'::date, '1 day'::interval) AS gs
)
SELECT
d.tanggal,
COALESCE(SUM(t.total_harga), 0) AS omzet_harian,
COUNT(t.id_transaksi) AS jml_transaksi
FROM deret d
LEFT JOIN transaksi t ON t.tanggal = d.tanggal
GROUP BY d.tanggal
ORDER BY d.tanggal;
Kunci polanya: deret di sisi kiri LEFT JOIN, transaksi di kanan. Semua tanggal dari deret pasti muncul, dan hari tanpa transaksi ngasih omzet 0.
Contoh kasus: tren harian Toko Berkah Januari
Toko Berkah, UMKM kelontong di dataset latihan ngulikdata, mau lihat tren penjualan harian Januari 2026. Tabel transaksinya cuma punya 27 tanggal berbeda di bulan itu.
Tanpa deret tanggal, GROUP BY biasa cuma ngasih 27 baris, dan grafiknya kelihatan mulus. Setelah pakai deret 31 hari plus LEFT JOIN, kebuka bahwa ada 4 hari dengan omzet nol. Ternyata semuanya jatuh di hari yang sama tiap minggu: Senin, waktu toko tutup buat kulakan.
Efeknya ke angka lumayan. Rata-rata harian versi lama (27 hari) sebesar Rp3.140.000. Versi jujur dengan 31 hari turun jadi Rp2.735.000, selisih 13%. Angka rata-rata yang lebih rendah ini yang dipakai buat nyetel target harian yang realistis, bukan target yang selalu meleset karena ngitung hari tutup sebagai penjualan.
Kesalahan umum saat generate deret tanggal
Naruh deret di sisi kanan JOIN. Kalau deret ada di kanan LEFT JOIN atau kamu pakai INNER JOIN, hari kosong balik ilang lagi. Deret harus di kiri LEFT JOIN.
Lupa COALESCE. Tanpa COALESCE, hari kosong ngasih NULL, bukan 0. NULL bikin SUM dan AVG di langkah berikutnya salah. Bungkus selalu.
Salah tipe di generate_series. Kalau lupa ::date, hasilnya timestamp dengan jam 00:00:00, dan JOIN ke kolom tanggal murni bisa meleset. Samain tipenya.
Batas recursive kekecilan di MySQL. Deret panjang kena batas 1000. Cek dulu kalau rentangmu lebih dari 3 tahun harian. Detail lengkap generate_series ada di dokumentasi PostgreSQL.
Deret tanggal vs tabel kalender: pilih mana?
Deret tanggal dibuat sekali pakai, isinya cuma kolom tanggal. Cocok buat kebutuhan cepat. Kalau kamu butuh atribut kayak nama hari, kuartal, atau penanda libur yang dipakai berulang di banyak laporan, lebih hemat bikin tabel kalender permanen.
| Kebutuhan | Pakai |
|---|---|
| Isi tanggal kosong sekali jalan | Deret tanggal |
| Atribut tanggal dipakai di banyak query | Tabel kalender |
| Butuh nama hari, kuartal, penanda libur | Tabel kalender |
FAQ
Kenapa perlu generate deret tanggal di SQL?
Kalau kamu GROUP BY tanggal dari tabel transaksi, hari yang nggak ada transaksinya bakal hilang dari hasil. Ini bikin grafik tren bolong dan rata-rata harian keliru. Dengan generate deret tanggal lengkap lalu LEFT JOIN ke data transaksi, tiap hari tetap muncul walau nilainya nol. Hasilnya laporan yang jujur nunjukin hari sepi, bukan cuma hari ramai.
Gimana cara generate deret tanggal di PostgreSQL?
Pakai generate_series dengan tanggal awal, tanggal akhir, dan interval. Contohnya generate_series('2026-01-01'::date, '2026-01-31'::date, '1 day'::interval). Ini ngasih 31 baris, satu buat tiap hari di Januari. Kamu bisa ganti interval jadi '1 week' atau '1 month' buat deret mingguan atau bulanan. generate_series ini fungsi bawaan PostgreSQL yang paling ringkas.
Gimana generate deret tanggal di MySQL yang nggak punya generate_series?
MySQL 8.0 ke atas pakai recursive CTE. Mulai dari tanggal awal, lalu tiap putaran tambah satu hari pakai INTERVAL 1 DAY, berhenti pas sampai tanggal akhir. SQL Server juga pakai pola yang sama. Buat MySQL di bawah 8.0 yang nggak dukung recursive CTE, kamu perlu tabel angka bantu atau tabel kalender yang disiapkan sebelumnya.
Apa beda deret tanggal dengan tabel kalender?
Deret tanggal cuma satu kolom berisi tanggal berurutan, dibuat sekali pakai saat butuh. Tabel kalender adalah tabel permanen dengan banyak kolom atribut per tanggal: tahun, bulan, kuartal, nama hari, penanda akhir pekan, dan hari libur. Deret tanggal pas buat kebutuhan cepat sekali jalan. Tabel kalender lebih hemat kalau dipakai berulang di banyak laporan.
Gimana cara isi tanggal kosong di laporan penjualan?
Generate deret tanggal buat rentang yang kamu mau, lalu LEFT JOIN deret itu ke tabel transaksi berdasarkan tanggal. Bungkus nilai penjualan pakai COALESCE biar hari tanpa transaksi tampil nol, bukan NULL. Dengan cara ini semua hari muncul berurutan di hasil, cocok buat grafik tren dan menghitung rata-rata harian yang akurat.
Latihan sekarang
- PostgreSQL pakai generate_series, MySQL dan SQL Server pakai recursive CTE yang nambah satu hari tiap putaran.
- Deret ditaruh di kiri LEFT JOIN, dan nilai kosong dibungkus COALESCE jadi nol.
- Buat atribut tanggal yang dipakai berulang, naik kelas ke tabel kalender.
Coba sekarang: bikin deret tanggal buat bulan lalu, LEFT JOIN ke data penjualanmu, dan lihat berapa hari yang ternyata nol. Latihan langsung bisa kamu lakuin di NgulikSQL. Lanjut ke CROSS JOIN SQL kalau kamu mau bikin kombinasi tanggal dengan daftar produk atau cabang sekaligus.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel terkait
Composite Index di SQL: Cara Kerja dan Urutan Kolom
Composite index itu index atas beberapa kolom sekaligus. Urutan kolomnya nentuin query mana yang kebantu, lewat aturan leftmost prefix.
Menghitung Stickiness (DAU/MAU) di SQL
Stickiness ngukur seberapa sering user balik lagi. Ini cara hitung DAU, MAU, dan rasio stickiness pakai SQL, plus contoh aplikasi UMKM.
Menghitung DAU dan MAU dengan SQL
DAU dan MAU dua metrik wajib buat produk digital. Ini cara hitungnya pakai SQL, lengkap query DISTINCT, per bulan, sampai rasio stickiness.