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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Cara pakai DATE_TRUNC di SQL buat memotong timestamp jadi awal bulan, minggu, atau jam. Kunci bikin laporan penjualan per periode yang rapi.
Cara mengisi tanggal kosong di time series SQL pakai generate_series dan LEFT JOIN biar grafik dan laporan gak bolong. Contoh penjualan harian UMKM.