Operator IN dan BETWEEN SQL: Filter Rentang & Daftar Nilai
TL;DR
Operator IN di SQL dipakai buat nyocokin sebuah kolom dengan daftar nilai, misalnya WHERE kota IN ('Bandung', 'Medan'), dan hasilnya sama dengan rangkaian OR tapi jauh lebih enak dibaca. Operator BETWEEN nyaring nilai di sebuah rentang, misalnya WHERE total BETWEEN 45000 AND 90000, dan batas atas maupun bawahnya ikut terhitung. Hati-hati dengan NOT IN: kalau daftarnya mengandung NULL, hasilnya selalu kosong.
IN dan BETWEEN itu dua operator yang bikin klausa WHERE kamu jadi enak dibaca.
WHERE kota IN ('Bandung', 'Medan')
WHERE total BETWEEN 45000 AND 90000
Sekilas nggak ada yang aneh. Tapi dua baris itu punya perilaku yang sering bikin angka laporan meleset — dan nggak ada error yang ngasih tau.
Apa itu operator IN di SQL?
IN adalah operator yang ngecek apakah nilai sebuah kolom ada di dalam daftar yang kamu kasih. Kalau ada, barisnya lolos filter. Hasilnya sama persis kayak nulis beberapa kondisi OR, tapi jauh lebih pendek.
-- Versi panjang
WHERE kota = 'Bandung' OR kota = 'Medan' OR kota = 'Jakarta'
-- Versi IN
WHERE kota IN ('Bandung', 'Medan', 'Jakarta')
Tiga kondisi jadi satu baris. Di query yang punya 8 kota, bedanya kerasa banget.
IN dipakai di klausa WHERE, sama kayak operator perbandingan lain.
Apa itu operator BETWEEN?
BETWEEN nyaring nilai yang ada di sebuah rentang, dan batas atas maupun bawahnya ikut kehitung. Ini yang paling sering disalahpahami.
WHERE total BETWEEN 45000 AND 90000
-- Sama persis dengan:
WHERE total >= 45000 AND total <= 90000
Perhatiin tanda sama dengannya. BETWEEN itu inklusif di dua sisi.
Contoh kasus: rentang harga di toko_berkah
Tabel penjualan toko_berkah, 10 transaksi Januari 2026.
| id | kota | kategori | total |
|---|---|---|---|
| 1 | Bandung | Minuman | 30.000 |
| 2 | Bandung | Makanan | 45.000 |
| 3 | Surabaya | Minuman | 45.000 |
| 4 | Surabaya | Sembako | 120.000 |
| 5 | Medan | Makanan | 90.000 |
| 6 | Bandung | Sembako | 120.000 |
| 7 | Medan | Minuman | 60.000 |
| 8 | Surabaya | Makanan | 45.000 |
| 9 | Bandung | Minuman | 30.000 |
| 10 | Medan | Sembako | 120.000 |
Bos minta daftar transaksi "menengah", antara 45.000 sampai 90.000.
SELECT id_transaksi, total FROM penjualan
WHERE total BETWEEN 45000 AND 90000;
-- id 2 (45000), id 3 (45000), id 5 (90000), id 7 (60000), id 8 (45000)
-- 5 baris
Sekarang coba yang eksklusif.
SELECT id_transaksi, total FROM penjualan
WHERE total > 45000 AND total < 90000;
-- id 7 (60000)
-- 1 baris
BETWEEN 45000 AND 90000 di toko_berkah ngasih 5 baris. Versi eksklusifnya cuma 1. Selisih 4 baris cuma gara-gara satu keputusan soal batas — dan nggak ada satu pun pesan error yang ngasih tau kamu salah pilih.
Sebelum nulis BETWEEN, tanya dulu: batasnya ikut atau nggak? Kalau bos bilang "di atas 45 ribu", itu eksklusif. Kalau bilang "mulai dari 45 ribu", itu inklusif.
Gimana cara pakai BETWEEN buat rentang tanggal?
Ini jebakan yang paling mahal, dan hampir semua analis pernah kena.
-- BERBAHAYA kalau kolomnya timestamp
WHERE tanggal BETWEEN '2026-01-01' AND '2026-01-31'
Database ngartiin '2026-01-31' sebagai 2026-01-31 00:00:00 — tengah malam. Transaksi yang terjadi jam 09:15 tanggal 31 Januari nilainya lebih besar dari tengah malam, jadi nggak ikut kesaring.
Kamu kehilangan satu hari penuh transaksi. Di toko yang ramai, itu jutaan rupiah yang hilang dari laporan.
Pola yang aman:
WHERE tanggal >= '2026-01-01'
AND tanggal < '2026-02-01'
Batas bawah inklusif, batas atas eksklusif ke awal bulan berikutnya. Pola ini bener buat kolom DATE maupun timestamp, dan nggak perlu kamu ubah kalau tipe kolomnya berubah nanti.
Aku pakai pola ini di semua laporan bulanan. Nggak pernah pakai BETWEEN buat tanggal lagi.
Kenapa NOT IN bisa ngasih hasil kosong?
Ini bug favorit SQL. Anggap ada tabel kota_ditutup yang isinya cabang yang lagi tutup.
CREATE TABLE kota_ditutup (kota TEXT);
INSERT INTO kota_ditutup VALUES ('Surabaya'), (NULL);
Baris NULL itu masuk gara-gara ada input kosong. Sekarang cari kota yang nggak tutup.
SELECT kota FROM penjualan
WHERE kota NOT IN (SELECT kota FROM kota_ditutup);
-- 0 baris 😵
Nol baris. Padahal Bandung dan Medan jelas nggak ada di daftar itu.
Penyebabnya: NOT IN itu sama dengan <> 'Surabaya' AND <> NULL. Dan SQL nggak bisa mastiin sebuah nilai "berbeda dari NULL" — soalnya NULL artinya "nggak tau". Hasil perbandingannya jadi nggak tau juga, dan barisnya gagal lolos.
Satu baris NULL bikin seluruh hasil query hilang. Tanpa error. Detail perilakunya di glosarium NULL.
Dua cara benerinnya:
-- A: buang NULL dari subquery
WHERE kota NOT IN (
SELECT kota FROM kota_ditutup WHERE kota IS NOT NULL
)
-- B: pakai NOT EXISTS (lebih aman, lebih cepat)
WHERE NOT EXISTS (
SELECT 1 FROM kota_ditutup k WHERE k.kota = penjualan.kota
)
Aku selalu pilih B. NOT EXISTS kebal dari jebakan NULL dan biasanya lebih ngebut di tabel besar.
Kapan IN mulai jadi lambat?
Buat daftar pendek, IN dan OR sama cepatnya — database ngoptimasi keduanya jadi rencana yang mirip.
Yang bikin lambat itu daftar yang kepanjangan. Kalau kamu nempel 5.000 ID pelanggan ke dalam IN (...), query-nya bakal berat dan bahkan bisa nabrak batas ukuran query.
Kalau daftarnya panjang, masukin ke tabel sementara terus JOIN. Jauh lebih cepat.
Aturan lengkap soal operator perbandingan bisa kamu cek di dokumentasi PostgreSQL untuk comparison functions.
Kesalahan umum waktu pakai IN dan BETWEEN
- Ngira BETWEEN itu eksklusif. Dia inklusif. Di toko_berkah, ini bedanya 5 baris vs 1 baris.
- Pakai BETWEEN buat kolom timestamp. Hari terakhirnya kepotong. Pakai
>=dan<. - NOT IN dengan subquery yang bisa ngasih NULL. Hasilnya kosong total.
- Kebalik urutan BETWEEN.
BETWEEN 90000 AND 45000selalu ngasih 0 baris. Angka kecil duluan. - Nempel ribuan nilai ke dalam IN. Pindahin ke tabel sementara, terus JOIN.
FAQ
Apakah BETWEEN termasuk batas atas dan bawahnya?
Iya, inklusif dua-duanya. BETWEEN 45000 AND 90000 sama dengan >= 45000 AND <= 90000. Baris yang nilainya tepat di batas ikut kesaring.
Kenapa NOT IN hasilnya kosong padahal datanya ada?
Daftarnya kemungkinan mengandung NULL. SQL nggak bisa mastiin sebuah nilai berbeda dari NULL, jadi semua baris gagal lolos. Pakai NOT EXISTS.
Mana yang lebih cepat, IN atau OR?
Buat daftar pendek, sama aja. Keunggulan IN ada di keterbacaan. Kalau daftarnya ratusan nilai, pakai tabel sementara plus JOIN.
Apakah IN bisa diisi hasil query lain?
Bisa: WHERE kota IN (SELECT kota FROM cabang_aktif). Tapi kalau subquery-nya bisa ngasih NULL, lebih aman pakai EXISTS.
Rangkuman
- IN ngeganti rangkaian OR jadi satu baris yang enak dibaca.
- BETWEEN inklusif di dua sisi. Buat tanggal, pakai
>=dan<— jangan BETWEEN. - NOT IN yang ketemu NULL ngasih hasil kosong tanpa error. Pakai NOT EXISTS.
Semua query di artikel ini udah dites dan siap copy-paste. Latihan langsung di halaman operator IN — editornya jalan di browser, nggak perlu install apa-apa.
Lanjut baca: Operator LIKE SQL buat nyari teks pakai wildcard.
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.