INTERSECT dan EXCEPT SQL: Cari Irisan dan Selisih Dataset
TL;DR
INTERSECT di SQL balikin baris yang muncul di dua hasil query sekaligus, jadi dipakai buat cari irisan dua dataset. EXCEPT (di MySQL dan Oracle namanya MINUS) balikin baris yang ada di query pertama tapi gak ada di query kedua, jadi dipakai buat cari selisih. Keduanya otomatis ngilangin duplikat, dan mensyaratkan jumlah serta tipe kolom di kedua query harus sama.
INTERSECT ngambil baris yang muncul di dua hasil query sekaligus. EXCEPT ngambil baris yang cuma ada di query pertama dan gak ada di query kedua.
Dua operator ini yang bikin pertanyaan "siapa pelanggan yang bulan lalu belanja tapi bulan ini nggak?" bisa dijawab dalam 5 baris SQL.
Tanpa mereka, kamu harus muter lewat LEFT JOIN plus WHERE IS NULL. Jalan sih, tapi lebih panjang dan lebih gampang salah.
Apa itu INTERSECT di SQL?
INTERSECT adalah operator set yang bandingin hasil dua query lalu cuma balikin baris yang muncul di keduanya. Baris duplikat otomatis dihapus.
SELECT kolom1, kolom2 FROM tabel_a
INTERSECT
SELECT kolom1, kolom2 FROM tabel_b;
Syaratnya cuma tiga:
- Jumlah kolom di kedua query harus sama.
- Tipe datanya harus kompatibel.
- Urutan kolomnya harus sama.
Kalau kolom pertama di query atas itu customer_id (integer) dan kolom pertama di query bawah itu nama (teks), database bakal nolak.
Apa itu EXCEPT di SQL?
EXCEPT balikin baris yang ada di query pertama tapi gak ada di query kedua. Urutan querynya penting — A EXCEPT B beda hasil dari B EXCEPT A.
SELECT kolom1 FROM tabel_a
EXCEPT
SELECT kolom1 FROM tabel_b;
Di Oracle, operator yang sama namanya MINUS. Fungsinya identik, cuma beda nama.
Sintaks lengkap dan aturan tipenya ada di dokumentasi combining queries PostgreSQL.
Tabel perbandingan operator set
| Operator | Balikin apa | Duplikat | Kasus pakai |
|---|---|---|---|
UNION | Semua baris dari dua query | Dihapus | Gabung data dari 2 bulan |
UNION ALL | Semua baris dari dua query | Dipertahankan | Gabung log, lebih cepat |
INTERSECT | Baris yang ada di keduanya | Dihapus | Pelanggan yang balik lagi |
EXCEPT | Baris yang cuma di query 1 | Dihapus | Pelanggan yang churn |
Kalau UNION masih agak samar, baca dulu perbedaan UNION dan UNION ALL. Konsepnya nyambung langsung ke sini.
Contoh kasus: churn pelanggan e-commerce
Aku pakai dua tabel dari dataset ngulikdata: transaksi_januari dan transaksi_februari. Ini toko online produk UMKM, 7 pelanggan unik di Januari, 6 di Februari.
DDL dan data lengkapnya ada di blok SQL artikel ini — tinggal copy-paste ke database latihanmu.
Kasus 1: siapa yang balik belanja?
SELECT customer_id, nama_customer
FROM transaksi_januari
INTERSECT
SELECT customer_id, nama_customer
FROM transaksi_februari
ORDER BY customer_id;
Hasilnya 3 pelanggan: Rina Wijaya (101), Sari Dewi (103), Maya Kusuma (105).
Perhatiin: Rina punya 2 transaksi di Januari, tapi di hasil dia cuma muncul sekali. INTERSECT otomatis ngilangin duplikat.
Kasus 2: siapa yang kabur?
SELECT customer_id, nama_customer
FROM transaksi_januari
EXCEPT
SELECT customer_id, nama_customer
FROM transaksi_februari
ORDER BY customer_id;
Hasilnya 4 pelanggan: Budi (102), Andi (104), Doni (106), Lina (107).
Ini daftar churn. Langsung bisa kamu kirim ke tim marketing buat kampanye win-back.
Kasus 3: siapa yang baru?
Tinggal balik urutannya:
SELECT customer_id, nama_customer
FROM transaksi_februari
EXCEPT
SELECT customer_id, nama_customer
FROM transaksi_januari
ORDER BY customer_id;
Hasilnya 3 pelanggan baru: Fajar (108), Tia (109), Hendra (110).
Query yang sama, urutan dibalik, pertanyaan yang dijawab beda total. Ini yang aku maksud tadi soal urutan penting.
Kasus 4: hitung churn rate sekalian
WITH churn AS (
SELECT customer_id FROM transaksi_januari
EXCEPT
SELECT customer_id FROM transaksi_februari
),
basis AS (
SELECT DISTINCT customer_id FROM transaksi_januari
)
SELECT
(SELECT COUNT(*) FROM churn) AS jumlah_churn,
(SELECT COUNT(*) FROM basis) AS pelanggan_januari,
ROUND(100.0 * (SELECT COUNT(*) FROM churn)
/ (SELECT COUNT(*) FROM basis), 1) AS churn_rate_persen;
Hasilnya: 4 churn dari 7 pelanggan Januari = churn rate 57,1%.
Angka segitu di toko online kecil itu wajar. Yang gak wajar adalah kalau kamu baru sadar setelah 6 bulan. Pakai CTE gini, query-nya bisa dijadwalkan jalan tiap awal bulan.
Gimana kalau database-ku gak dukung INTERSECT?
MySQL baru dukung INTERSECT dan EXCEPT dari versi 8.0.31. Kalau kamu masih di 5.7, dua pola ini penggantinya.
INTERSECT → INNER JOIN
SELECT DISTINCT j.customer_id, j.nama_customer
FROM transaksi_januari j
INNER JOIN transaksi_februari f
ON j.customer_id = f.customer_id;
DISTINCT wajib. Tanpa itu, Rina yang punya 2 transaksi Januari bakal muncul dua kali.
EXCEPT → LEFT JOIN + IS NULL
SELECT DISTINCT j.customer_id, j.nama_customer
FROM transaksi_januari j
LEFT JOIN transaksi_februari f
ON j.customer_id = f.customer_id
WHERE f.customer_id IS NULL;
Pola ini namanya anti-join. Baris yang gak nemu pasangan di tabel kanan bakal punya NULL, dan itu yang kita saring.
Kalau bagian JOIN-nya masih bikin pusing, cek dulu perbedaan INNER, LEFT, dan RIGHT JOIN.
Kesalahan umum waktu pakai INTERSECT dan EXCEPT
1. Pakai SELECT * di kedua sisi
Kelihatannya praktis. Tapi begitu salah satu tabel nambah kolom, query-mu langsung error "each query must have the same number of columns". Sebut kolomnya eksplisit.
2. Urutan kolom ketuker
SELECT customer_id, kota FROM transaksi_januari
INTERSECT
SELECT kota, customer_id FROM transaksi_februari; -- salah
Kalau tipenya kebetulan kompatibel, database gak protes — dia cuma bandingin customer_id sama kota. Hasilnya nol baris dan kamu bingung kenapa.
3. Lupa kalau duplikat kehapus
Kalau kamu butuh ngitung berapa kali sebuah baris muncul, INTERSECT bakal ngerusak hitunganmu. Pakai INTERSECT ALL atau EXCEPT ALL di PostgreSQL.
4. Salah kolom pembanding
Kalau kamu masukin total_belanja ke dalam SELECT, baris cuma dianggap sama kalau nilai belanjanya juga sama persis. Rina belanja 450.000 di Januari dan 380.000 di Februari — jadi dia gak bakal muncul di INTERSECT.
Bandingin cuma kolom identitas: customer_id, bukan nilai transaksinya.
5. ORDER BY ditaruh di query pertama
SELECT customer_id FROM transaksi_januari ORDER BY customer_id -- salah
EXCEPT
SELECT customer_id FROM transaksi_februari;
ORDER BY cuma boleh ada satu, di paling bawah, dan berlaku buat hasil gabungan. Taruh di akhir query.
FAQ
Apa bedanya INTERSECT dan INNER JOIN?
INNER JOIN nggabungin kolom dari dua tabel dan bisa bikin baris berlipat. INTERSECT bandingin seluruh baris hasil dua query dan otomatis ngilangin duplikat.
MySQL dukung INTERSECT dan EXCEPT?
Cuma dari versi 8.0.31 ke atas. Di bawah itu, pakai INNER JOIN dan LEFT JOIN + IS NULL sebagai penggantinya.
Kenapa INTERSECT saya error jumlah kolom?
Kedua query harus punya jumlah kolom sama, tipe kompatibel, dan urutan sama. Jangan pakai SELECT *.
INTERSECT ngilangin duplikat?
Iya, sama kayak UNION. Kalau butuh duplikat tetap ada, pakai INTERSECT ALL di PostgreSQL.
Mana yang lebih cepat, EXCEPT atau NOT IN?
EXCEPT biasanya lebih cepat dan lebih aman, karena NOT IN bakal balikin nol baris kalau subquery-nya ngandung NULL.
Yang perlu kamu bawa pulang
INTERSECT buat cari yang sama-sama ada. EXCEPT buat cari yang cuma ada di satu sisi. Urutan query di EXCEPT nentuin hasilnya — bolak-balik, dapet dua jawaban berbeda.
Coba sekarang: ambil tabel transaksi bulan lalu dan bulan ini di kerjaanmu, jalanin query EXCEPT, dan lihat berapa pelanggan yang hilang. Itu daftar prioritas follow-up kamu minggu ini.
Lanjut: UNION vs UNION ALL buat lengkapin pemahaman operator set, atau referensi operator EXCEPT buat sintaks per database.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel Terkait
7 SQL Client Gratis Terbaik buat Analis Data (2026)
Nggak perlu bayar buat nulis query. Ini 7 SQL client gratis yang beneran dipakai analis, plus kelebihan dan kekurangannya masing-masing.
SQL Style Guide: Cara Nulis Query yang Enak Dibaca Tim
Sepuluh aturan SQL style guide yang bikin query kamu kebaca sama tim — dan sama kamu sendiri 6 bulan lagi. Lengkap dengan contoh sebelum-sesudah.
Take-Home Test SQL Data Analyst: Contoh Soal + Cara Ngerjainnya
Contoh soal take-home test SQL yang beneran dipakai perusahaan, dikerjain step by step — dari baca soal, nulis query, sampai nyusun insight yang bikin recruiter nengok.