TL;DR
DATE_TRUNC di SQL memotong sebuah timestamp ke awal satuan waktu yang dipilih, misalnya awal bulan, minggu, atau jam. Sintaksnya DATE_TRUNC('month', tanggal), dan paling sering dipakai bareng GROUP BY buat bikin laporan penjualan per periode. Ekspresi yang sama harus muncul di SELECT dan GROUP BY.
DATE_TRUNC di SQL memotong sebuah timestamp ke awal satuan waktu yang kamu pilih, misalnya awal bulan, awal minggu, atau awal jam. Fungsi ini bikin banyak tanggal yang detail jadi rapi dikelompokkan, jadi kunci utama buat laporan penjualan per periode.
Masalahnya umum: kamu punya ribuan transaksi dengan timestamp sampai ke detik. Mau lihat total per bulan, tapi GROUP BY tanggal malah bikin ratusan grup karena tiap detik dianggap beda.
Di sini kita bahas cara DATE_TRUNC nyelesaiin ini. Contohnya laporan bulanan toko.
DATE_TRUNC adalah fungsi yang membulatkan timestamp ke bawah, ke awal periode tertentu. Kalau kamu truncate ke month, tanggal 17 Agustus jam 14:30 jadi 1 Agustus jam 00:00. Semua transaksi dalam bulan yang sama jadi punya nilai yang identik, sehingga gampang dikelompokkan.
Bedanya sama EXTRACT: EXTRACT ngambil satu bagian angka, misalnya angka bulan 8. DATE_TRUNC ngembaliin tanggal utuh di awal periode, jadi urutan waktunya tetap kejaga buat grafik.
Sintaksnya: DATE_TRUNC('satuan', timestamp). Argumen pertama satuan waktu dalam tanda kutip, argumen kedua kolom tanggalnya. Satuan yang umum: hour, day, week, month, quarter, dan year.
SELECT DATE_TRUNC('month', '2026-08-17 14:30:00'::timestamp);
-- Hasil: 2026-08-01 00:00:00
Paling sering dipakai bareng GROUP BY buat ngeringkas data. Kamu truncate kolom tanggalnya, lalu grup dan jumlahkan.
SELECT
DATE_TRUNC('month', tanggal) AS bulan,
SUM(omzet) AS total_omzet
FROM penjualan
GROUP BY DATE_TRUNC('month', tanggal)
ORDER BY bulan;
Hasilnya satu baris per bulan dengan total omzetnya. Bersih dan urut. Ini pola dasar hampir semua laporan periodik.
DATE_TRUNC nerima banyak satuan, dari yang kecil kayak detik sampai yang besar kayak tahun. Kamu tinggal ganti argumen pertamanya.
| Satuan | Contoh input | Hasil |
|---|---|---|
| hour | 2026-08-17 14:30 | 2026-08-17 14:00 |
| day | 2026-08-17 14:30 | 2026-08-17 00:00 |
| week | 2026-08-17 (Senin) | 2026-08-17 00:00 |
| month | 2026-08-17 | 2026-08-01 |
| quarter | 2026-08-17 | 2026-07-01 |
Perhatiin week: di PostgreSQL, minggu dimulai hari Senin. Jadi truncate ke minggu bakal geser ke Senin terdekat sebelumnya.
toko_berkah punya tabel penjualan berisi 8.400 transaksi selama setahun, masing-masing dengan timestamp lengkap. Manajer mau lihat tren omzet bulanan dan pertumbuhannya.
SELECT
DATE_TRUNC('month', tanggal) AS bulan,
COUNT(*) AS jml_transaksi,
SUM(omzet) AS total_omzet
FROM penjualan
GROUP BY DATE_TRUNC('month', tanggal)
ORDER BY bulan;
Dari dataset ngulikdata, hasilnya bikin satu pola kelihatan jelas: omzet bulan Ramadan melonjak jadi Rp 142 juta, hampir dua kali lipat dari rata-rata bulan biasa yang Rp 78 juta. Tanpa DATE_TRUNC, lonjakan ini kependam di antara 8.400 baris dan gak keliatan.
Begitu data diringkas per bulan, kamu bisa lanjut hitung pertumbuhan bulan ke bulan atau bandingin tahun ke tahun. Semua berawal dari truncate yang benar.
Buat rapiin tampilan, biasanya hasil DATE_TRUNC diformat lagi pakai TO_CHAR, misalnya jadi teks 'Agustus 2026'. Tapi buat pengurutan, biarin dalam bentuk tanggal.
DATE_TRUNC ngembaliin tanggal utuh yang dibulatkan ke awal periode, misalnya 1 Agustus buat semua tanggal di bulan Agustus. EXTRACT cuma ngambil satu angka dari tanggal, misalnya angka 8 buat bulan. Pakai DATE_TRUNC kalau mau kelompokkan sambil jaga urutan waktu. Pakai EXTRACT kalau cuma butuh komponen angkanya buat filter atau perhitungan.
Di PostgreSQL, DATE_TRUNC dengan satuan week selalu mulai dari hari Senin, ikut standar ISO. Jadi tanggal berapa pun bakal digeser ke Senin di minggu yang sama. Kalau bisnismu ngitung minggu mulai hari Minggu, kamu perlu penyesuaian manual, misalnya kurangi satu hari sebelum truncate lalu tambahin lagi setelahnya.
Biasanya karena ekspresi di SELECT dan GROUP BY gak sama persis. Kalau kamu tulis DATE_TRUNC('month', tanggal) di SELECT, GROUP BY-nya juga harus pakai ekspresi yang sama, bukan cuma nama kolom. Alternatifnya, kasih alias lalu GROUP BY berdasarkan posisi kolom, misalnya GROUP BY 1, biar gak perlu nulis ulang.
MySQL gak punya fungsi DATE_TRUNC. Buat efek serupa, kamu pakai DATE_FORMAT, misalnya DATE_FORMAT(tanggal, '%Y-%m-01') buat mendapatkan awal bulan. Buat truncate ke minggu atau jam, kombinasiin fungsi kayak DATE, WEEK, atau FLOOR. PostgreSQL, BigQuery, dan Snowflake punya DATE_TRUNC bawaan yang lebih ringkas.
Bisa. Pakai satuan hour, misalnya DATE_TRUNC('hour', waktu_transaksi). Semua transaksi dalam jam yang sama bakal punya nilai identik, jadi gampang dikelompokkan. Ini berguna buat analisis pola jam sibuk, misalnya lihat jam berapa toko paling ramai. Menitnya dibuang, cuma awal jamnya yang disimpan.
Rekap: DATE_TRUNC motong timestamp ke awal periode kayak bulan atau minggu, biar data gampang dikelompokkan. Pasangin sama GROUP BY dan pastiin ekspresinya sama di dua tempat.
Coba jalanin query bulanan ini di data transaksimu, lalu lihat tren yang tadinya kependam di antara ribuan baris.
Mau lanjut ngulik SQL tanggal? Baca cara mengisi tanggal kosong di time series SQL dan cara bikin tabel kalender di SQL. Buat konsep dasarnya, cek halaman fungsi DATE_TRUNC dan glosarium time series. Dokumentasi resmi ada di dokumentasi PostgreSQL untuk fungsi tanggal.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Nambah 30 hari ke tanggal invoice, ngurangin sebulan buat cari periode lalu, ngitung selisih hari antar order. Semua itu aritmetika tanggal, dan SQL punya operator INTERVAL buat ngerjainnya.
Ngurangin tahun sekarang sama tahun lahir kelihatan gampang, tapi hasilnya sering meleset setahun kalau ulang tahunnya belum lewat. Ini cara hitung umur yang akurat di SQL.
Cara mengisi tanggal kosong di time series SQL pakai generate_series dan LEFT JOIN biar grafik dan laporan gak bolong. Contoh penjualan harian UMKM.