Menghitung Umur dari Tanggal Lahir di SQL
TL;DR
Menghitung umur dari tanggal lahir di SQL paling akurat pakai fungsi bawaan tanggal, bukan sekadar ngurangin tahun. Di PostgreSQL, EXTRACT(YEAR FROM AGE(tanggal_lahir)) ngasih umur penuh dalam tahun yang udah memperhitungkan apakah ulang tahun sudah lewat. Di MySQL, pakai TIMESTAMPDIFF(YEAR, tanggal_lahir, CURDATE()). Selisih tahun polos rawan meleset setahun karena nggak ngecek tanggal dan bulan.
Menghitung umur dari tanggal lahir di SQL paling aman pakai fungsi tanggal bawaan, bukan cuma ngurangin dua angka tahun. Selisih tahun polos gampang meleset setahun.
Kasusnya sederhana. Kamu punya kolom tanggal_lahir dan mau tau umur pelanggan hari ini. Buat segmentasi promo, buat cek eligibility, atau buat laporan demografi.
Di artikel ini kamu bakal dapat query yang jalan di PostgreSQL dan MySQL, plus cara ngindarin jebakan yang bikin umur salah setahun.
Apa maksudnya menghitung umur di SQL?
Menghitung umur di SQL adalah nyari selisih waktu antara tanggal lahir dan tanggal hari ini, lalu dinyatakan dalam tahun penuh. Umur penuh artinya ulang tahun yang belum lewat tahun ini nggak dihitung. Orang lahir Desember 1998 baru genap 27 tahun setelah Desember, bukan awal tahun.
Kunci akurasi ada di pengecekan bulan dan tanggal, bukan cuma tahun. Ini yang sering kelewat waktu orang buru-buru pakai pengurangan biasa.
Gimana cara hitung umur di PostgreSQL?
Di PostgreSQL, cara paling bersih pakai fungsi AGE() dibungkus EXTRACT(). AGE ngitung selisih jadi interval tahun-bulan-hari, lalu EXTRACT ngambil bagian tahunnya aja. Hasilnya umur penuh yang udah otomatis ngecek apakah ulang tahun sudah lewat.
SELECT
nama,
tanggal_lahir,
EXTRACT(YEAR FROM AGE(tanggal_lahir)) AS umur
FROM pelanggan;
AGE dengan satu argumen otomatis pakai tanggal hari ini sebagai pembanding. Kalau mau ngunci ke tanggal tertentu, kasih dua argumen: AGE('2026-08-30', tanggal_lahir).
Butuh umur dalam satuan lain? Ganti YEAR jadi MONTH buat bayi, atau pakai EXTRACT(DAY FROM ...) buat selisih hari. Buat dasar soal EXTRACT, cek fungsi EXTRACT di SQL.
Gimana cara hitung umur di MySQL?
MySQL nggak punya AGE, tapi punya TIMESTAMPDIFF() yang lebih langsung. Fungsi ini ngasih selisih dua tanggal dalam satuan yang kamu pilih. Buat umur, pakai satuan YEAR dan bandingin tanggal lahir dengan CURDATE().
SELECT
nama,
tanggal_lahir,
TIMESTAMPDIFF(YEAR, tanggal_lahir, CURDATE()) AS umur
FROM pelanggan;
Bagusnya, TIMESTAMPDIFF udah ngitung umur penuh dengan benar. Dia ngecek bulan dan tanggal, jadi orang yang ulang tahunnya minggu depan masih dihitung umur lama. Ini beda sama pengurangan YEAR() yang bakal aku bahas di bagian kesalahan umum.
Gimana kalau butuh umur dalam tahun dan bulan?
Kadang umur tahun aja kurang, misalnya buat data anak atau masa kerja. Di PostgreSQL, AGE tanpa EXTRACT langsung ngasih interval lengkap. Tinggal tampilkan apa adanya atau ambil per komponen.
SELECT
nama,
AGE(tanggal_lahir) AS umur_lengkap,
EXTRACT(YEAR FROM AGE(tanggal_lahir)) AS tahun,
EXTRACT(MONTH FROM AGE(tanggal_lahir)) AS bulan
FROM pelanggan;
Hasil umur_lengkap bentuknya kayak 27 years 3 mons 12 days. Rapi buat ditampilkan, gampang dipecah buat dihitung lanjut.
Kalau kamu sering main sama selisih tanggal kayak gini, aritmetika interval lain juga berguna. Ada bahasan terpisah soal operasi interval dan aritmetika tanggal di SQL.
Contoh kasus: segmentasi umur pelanggan toko_berkah
Toko_berkah, UMKM sembako yang datanya sering aku pakai buat latihan, punya tabel pelanggan dengan 1.240 baris. Manajernya mau tau sebaran umur buat nentuin channel promo: WhatsApp buat yang lebih tua, Instagram buat yang muda.
Query ini ngelompokkan pelanggan ke bracket umur pakai CASE.
SELECT
CASE
WHEN umur < 25 THEN '18-24'
WHEN umur < 35 THEN '25-34'
WHEN umur < 45 THEN '35-44'
ELSE '45+'
END AS bracket_umur,
COUNT(*) AS jumlah
FROM (
SELECT EXTRACT(YEAR FROM AGE(tanggal_lahir)) AS umur
FROM pelanggan
) t
GROUP BY bracket_umur
ORDER BY bracket_umur;
Dari 1.240 pelanggan, hasilnya: bracket 25-34 paling gede dengan 512 orang (41%), disusul 35-44 sebanyak 358 orang. Bracket 45+ cuma 174 orang. Angka ini bikin manajernya milih Instagram sebagai channel utama, soalnya dua bracket termuda gabungan udah 63% dari total.
Untuk bikin bracket kayak gini lebih rapi, teknik bucketing data juga bisa dipakai di dimensi lain, bukan cuma umur.
Kesalahan umum saat hitung umur di SQL
Jebakan paling sering: ngurangin tahun doang. Query kayak YEAR(CURDATE()) - YEAR(tanggal_lahir) keliatan benar, tapi salah buat orang yang belum ulang tahun tahun ini.
Contohnya orang lahir 20 Desember 1998. Per 30 Agustus 2026, umur asli dia masih 27. Tapi 2026 - 1998 ngasih 28. Meleset setahun karena Desember belum lewat.
| Metode | Hasil (lahir 20 Des 1998, per 30 Agu 2026) | Akurat? |
|---|---|---|
| YEAR sekarang - YEAR lahir | 28 | Nggak |
| TIMESTAMPDIFF(YEAR, ...) | 27 | Ya |
| EXTRACT(YEAR FROM AGE(...)) | 27 | Ya |
Kesalahan kedua: nyimpen umur sebagai kolom tetap. Umur berubah tiap tahun. Kalau kamu simpan angka 27 hari ini, tahun depan datanya udah basi. Simpan tanggal_lahir, hitung umur pas query. Biar selalu update.
Referensi resmi soal fungsi tanggal PostgreSQL ada di dokumentasi PostgreSQL.
FAQ
Kenapa umur di SQL bisa meleset setahun?
Karena kamu ngurangin tahun tanpa ngecek bulan dan tanggal. Orang yang ulang tahunnya belum lewat tahun ini belum nambah umur, tapi selisih tahun polos udah nganggap dia bertambah. Pakai TIMESTAMPDIFF di MySQL atau AGE di PostgreSQL yang otomatis ngecek tanggal lengkap, jadi hasilnya nggak kelebihan setahun.
Fungsi mana yang paling akurat buat hitung umur?
Di PostgreSQL pakai EXTRACT(YEAR FROM AGE(tanggal_lahir)). Di MySQL pakai TIMESTAMPDIFF(YEAR, tanggal_lahir, CURDATE()). Dua-duanya ngitung umur penuh dan udah memperhitungkan apakah ulang tahun sudah lewat. Hindari DATEDIF gaya spreadsheet atau pengurangan YEAR karena rawan salah setahun.
Perlu nggak nyimpan umur di kolom database?
Nggak usah. Umur berubah tiap tahun, jadi angka yang kamu simpan hari ini bakal basi. Simpan tanggal lahir sebagai kolom DATE, lalu hitung umur pas dibutuhin di query atau di view. Kalau butuh performa buat data gede, bikin kolom terhitung atau materialized view yang di-refresh berkala.
Gimana cara hitung umur per tanggal tertentu, bukan hari ini?
Ganti pembanding hari ini dengan tanggal yang kamu mau. Di PostgreSQL, AGE terima dua argumen: AGE('2026-12-31', tanggal_lahir). Di MySQL, ganti CURDATE() dengan tanggal literal di TIMESTAMPDIFF. Ini berguna buat ngitung umur pas transaksi terjadi, bukan umur sekarang.
Gimana kalau ada tanggal lahir yang NULL?
Fungsi umur bakal ngasih NULL juga kalau input NULL, jadi barisnya nggak error tapi kolom umurnya kosong. Kamu bisa saring pakai WHERE tanggal_lahir IS NOT NULL, atau kasih nilai default pakai COALESCE kalau mau tetap nampil. Pilih sesuai kebutuhan laporan.
Penutup
Poin utamanya: jangan hitung umur dari selisih tahun doang. Pakai AGE di PostgreSQL atau TIMESTAMPDIFF di MySQL biar akurat. Dan simpan tanggal lahir, bukan angka umur, biar datanya nggak basi.
Mau latihan query tanggal langsung tanpa install database? Coba tulis dan jalanin sendiri di NgulikSQL.
Lanjut baca yang berkaitan: operasi interval dan aritmetika tanggal di SQL dan membuat tabel kalender di SQL.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel terkait
Semi Join dan Anti Join di SQL: Filter Pakai Tabel Lain
Semi join ngambil baris yang punya pasangan di tabel lain, anti join ngambil yang nggak punya. Keduanya filter, bukan gabung kolom. Ini cara nulisnya di SQL pakai EXISTS dan NOT EXISTS.
Crosstab (Pivot) di PostgreSQL: Ubah Baris Jadi Kolom
Crosstab di PostgreSQL mivot data dari format panjang (baris) jadi format lebar (kolom), mirip pivot table Excel. Butuh extension tablefunc, dan ada alternatif pakai CASE atau FILTER kalau kolomnya tetap.
INSERT ON CONFLICT di PostgreSQL
INSERT ON CONFLICT bikin PostgreSQL insert baris baru atau update yang udah ada dalam satu perintah, tanpa error gara-gara duplikat primary key.