Penjelasan sederhana
WITH atau CTE (Common Table Expression) memberi nama pada hasil sebuah query, lalu nama itu bisa dipakai seperti tabel biasa di query berikutnya. Anggap saja seperti membuat sheet bantu di Excel.
Hasilnya sama saja dengan subquery, tetapi jauh lebih mudah dibaca karena langkahnya tersusun dari atas ke bawah: hitung ini dulu, beri nama, lalu pakai.
Sintaks
WITH nama_cte AS (
SELECT ...
)
SELECT ...
FROM nama_cte;
| Bagian | Keterangan |
|---|---|
nama_cte | Nama tabel sementara. Hanya berlaku di query ini. |
beberapa CTE | Pisahkan dengan koma: WITH a AS (...), b AS (...) SELECT ... |
Tanda [kurung siku] berarti bagian opsional. Kata kunci SQL tidak membedakan huruf besar-kecil, tapi menulisnya dengan huruf besar membuat query lebih mudah dibaca.
Contoh WITH (CTE)
Data contoh: karyawan, penjualan
Tabel karyawan
| id | nama | dept_id | kota | gaji | tgl_masuk | atasan_id |
|---|---|---|---|---|---|---|
| 1 | Andi Pratama | 3 | Bandung | 12500000 | 2019-03-11 | NULL |
| 2 | Bunga Lestari | 1 | Jakarta | 9800000 | 2020-07-01 | NULL |
| 3 | Candra Wijaya | 3 | Bandung | 8200000 | 2021-02-15 | 1 |
| 4 | Dewi Anggraini | 2 | Jakarta | 7500000 | 2022-05-09 | 6 |
| 5 | Eko Saputra | 1 | Jakarta | 6900000 | 2023-01-16 | 2 |
| 6 | Fajar Nugroho | 2 | Surabaya | 11000000 | 2018-09-03 | NULL |
| 7 | Gita Permata | 3 | Jakarta | 8200000 | 2023-08-21 | 1 |
| 8 | Hendra Gunawan | NULL | Medan | 5500000 | 2024-04-02 | NULL |
Tabel penjualan
| id | tanggal | karyawan_id | produk | kategori | qty | harga |
|---|---|---|---|---|---|---|
| 1 | 2026-01-05 | 4 | Laptop | Elektronik | 2 | 8500000 |
| 2 | 2026-01-12 | 6 | Printer | Elektronik | 1 | 2300000 |
| 3 | 2026-01-20 | 4 | Kursi Kantor | Furnitur | 5 | 1200000 |
| 4 | 2026-02-03 | 6 | Laptop | Elektronik | 1 | 8500000 |
| 5 | 2026-02-14 | 4 | Meja Kerja | Furnitur | 3 | 1750000 |
| 6 | 2026-02-25 | 5 | Kertas A4 | ATK | 20 | 55000 |
| 7 | 2026-03-02 | 6 | Kursi Kantor | Furnitur | 4 | 1200000 |
| 8 | 2026-03-10 | 4 | Printer | Elektronik | 2 | 2300000 |
| 9 | 2026-03-18 | 5 | Kertas A4 | ATK | 30 | 55000 |
| 10 | 2026-03-27 | 6 | Monitor | Elektronik | 3 | 1900000 |
WITH omzet_sales AS (
SELECT karyawan_id, SUM(qty * harga) AS omzet
FROM penjualan
GROUP BY karyawan_id
)
SELECT k.nama, o.omzet
FROM omzet_sales AS o
JOIN karyawan AS k ON k.id = o.karyawan_id
ORDER BY o.omzet DESC;
Hasil 3 baris
| nama | omzet |
|---|---|
| Dewi Anggraini | 32850000 |
| Fajar Nugroho | 21300000 |
| Eko Saputra | 2750000 |
Omzet dihitung per karyawan di CTE, lalu digabung ke tabel karyawan untuk mengambil namanya.
Cara kerjanya, langkah demi langkah
- Bagian
WITH omzet_sales AS (...)menghitung total omzet per karyawan dari tabel penjualan. Hasil sementaranya: karyawan 4 = 32.850.000, karyawan 6 = 21.300.000, karyawan 5 = 2.750.000. - Hasil itu diberi nama omzet_sales dan dipakai seperti tabel.
JOIN karyawanmengambil nama dari tabel karyawan: id 4 adalah Dewi, id 6 Fajar, id 5 Eko.ORDER BY o.omzet DESC: diurutkan dari omzet terbesar.
Dipakai untuk apa di kantor?
- Laporan bertingkat: hitung per bulan dulu, lalu hitung pertumbuhannya.
- Memecah query panjang menjadi beberapa langkah yang mudah dicek satu per satu.
Kesalahan yang sering terjadi
- Lupa koma di antara beberapa CTE:
WITH a AS (...), b AS (...). - Mengira CTE tersimpan permanen. Ia hanya berlaku untuk query itu saja.
EXISTS