Database••7 min read•14 views

SELECT, WHERE, dan Filtering Data — Seni Mengambil Data Secara Presisi

Pelajari cara menyaring data SQL secara presisi. Pahami urutan eksekusi query, bahaya SELECT *, penggunaan LIKE/ILIKE, hingga cara menangani nilai NULL dengan benar.

Setelah di Artikel Pertama  kita sudah berhasil menyiapkan environment PostgreSQL menggunakan Docker dan memahami perintah dasar pembentukan skema (DDL) serta manipulasi data (DML), sekarang saatnya kita melangkah ke tahap yang paling sering dilakukan dalam kehidupan sehari-hari seorang software engineer: mengambil dan menyaring data.

Banyak pengembang menganggap perintah SELECT adalah hal yang sepele. "Ah, cuma SELECT * FROM table, apa susahnya?" Namun di dunia kerja nyata, menarik seluruh data menggunakan tanda bintang (*) adalah salah satu penyebab utama aplikasi melambat, memory footprint membengkak, dan database server mengalami kemacetan (bottleneck).

Pada artikel kedua ini, kita akan membongkar cara kerja klausa SELECT dan WHERE, memahami teknik filtering data tingkat lanjut, serta bagaimana SQL Engine memproses query yang kita tulis di balik layar.

1. Anatomi Perintah SELECT: Mengapa SELECT * Adalah Antipattern?

Secara sederhana, perintah SELECT digunakan untuk menentukan kolom mana saja yang ingin kita tampilkan dari satu atau beberapa tabel.

Bahasa Deklaratif & Alur Eksekusi Logical

Ketika kamu menulis baris perintah SQL, urutan penulisan kode berbeda dengan urutan bagaimana database mengeksekusinya di balik layar.

SQL
-- Urutan Penulisan (Syntax Order)
SELECT id, username, email
FROM users
WHERE is_active = TRUE;
Di balik layar, SQL Engine memprosesnya dengan alur seperti ini:

  1. FROM users: Database menentukan tabel sumber data terlebih dahulu.
  2. WHERE is_active = TRUE: Database menyaring baris-baris (rows) yang tidak memenuhi kondisi.
  3. SELECT id, username, email: Database baru memilih dan memproyeksikan kolom-kolom (columns) yang diminta dari hasil penyaringan.

Bahaya Bahaya Latent SELECT *

Menulis SELECT * FROM posts; memang cepat saat fase prototyping. Namun, membawa kebiasaan ini ke lingkungan produksi (production) sangat tidak disarankan karena beberapa alasan:

  1. Pemborosan I/O & Memori: Memaksa database membaca kolom yang tidak dibutuhkan (terutama kolom bertipe teks panjang seperti konten atau JSONB) dari disk ke RAM, lalu mengalirkannya melalui jaringan ke aplikasi kamu.
  2. Merusak Cache Aplikasi: Menambah kolom baru di tabel akan mengubah bentuk payload data yang ditarik, yang bisa merusak mekanisme caching atau serialization di sisi kode backend.
  3. Penyebab Query Lambat: SELECT * sering kali mencegah PostgreSQL memanfaatkan Index-Only Scan (fitur di mana database cukup membaca indeks tanpa perlu menyentuh disk utama).
Best Practice: Selalu sebutkan secara eksplisit nama kolom yang kamu butuhkan.

SQL
-- GOOD PRACTICE
SELECT id, judul, status FROM posts;

2. Menyaring Data Spesifik dengan Klausa WHERE & Operator Logika

Klausa WHERE digunakan untuk memfilter baris data (rows) berdasarkan kriteria tertentu. Hanya baris yang menghasilkan nilai evaluasi TRUE yang akan dikembalikan oleh database.

Mari kita gunakan sampel data dari [Artikel 1] (tabel users dan posts) untuk mempraktikkan query di bawah ini.

A. Operator Perbandingan Standard (=, !=, <, >, <=, >=)

SQL
-- Mengambil pengguna yang berstatus aktif
SELECT id, username, email 
FROM users 
WHERE is_active = TRUE;

-- Mengambil postingan selain berstatus 'draft'
SELECT id, judul, status 
FROM posts 
WHERE status != 'draft'; -- atau menggunakan operator <>

B. Menggabungkan Kondisi: AND, OR, dan NOT

Kamu bisa mengombinasikan beberapa syarat penyaringan menggunakan operator logika.

SQL
-- Mengambil postingan milik user_id = 1 DAN berstatus 'published'
SELECT id, judul, status 
FROM posts 
WHERE user_id = 1 AND status = 'published';

-- Mengambil postingan yang statusnya 'draft' ATAU milik user_id = 2
SELECT id, judul, user_id, status 
FROM posts 
WHERE status = 'draft' OR user_id = 2;
Hati-hati dengan Prioritas Operator (Precedence):
Operator AND memiliki prioritas lebih tinggi daripada OR. Jika kamu menggabungkannya dalam satu query, selalu gunakan tanda kurung () untuk memperjelas logika yang diinginkan.

SQL
-- Dapatkan post milik user 1 atau user 2, TAPI hanya yang statusnya 'published'
SELECT id, judul, user_id, status 
FROM posts 
WHERE (user_id = 1 OR user_id = 2) 
  AND status = 'published';

3. Filtering Tingkat Lanjut: Range, List, dan Pattern Matching

Dalam aplikasi nyata, pencarian data jarang sekali menggunakan persis sama dengan (=). Kita sering kali harus mencari data berdasarkan rentang angka, pilihan daftar (list), atau pencarian teks (search bar).

A. Menggunakan IN dan NOT IN (Filtering Daftar Value)

Daripada menulis rentetan OR yang panjang (WHERE id = 1 OR id = 2 OR id = 5), gunakan operator IN:

SQL
-- Mengambil user berdasarkan ID tertentu
SELECT id, username, nama_lengkap 
FROM users 
WHERE id IN (1, 2, 5);

-- Mengecualikan status tertentu
SELECT id, judul, status 
FROM posts 
WHERE status NOT IN ('archived', 'deleted');

B. Menggunakan BETWEEN (Filtering Rentang Nilai/Tanggal)

Operator BETWEEN bersifat inclusive (artinya batas awal dan batas akhir ikut dihitung).

SQL
-- Mengambil artikel yang dibuat sepanjang bulan November 2025
SELECT id, judul, created_at 
FROM posts 
WHERE created_at BETWEEN '2025-11-01 00:00:00' AND '2025-11-30 23:59:59';

C. Pencarian Teks: LIKE, ILIKE, dan Wildcard

Untuk fitur pencarian (search feature), SQL menyediakan pencarian pola menggunakan simbol wildcard:

  • % (persen): Mewakili nol, satu, atau banyak karakter.
  • _ (garis bawah): Mewakili tepat satu karakter.
SQL
-- Pencarian Case-Sensitive (LIKE)
-- Mencari judul yang diawali kata 'Panduan'
SELECT id, judul 
FROM posts 
WHERE judul LIKE 'Panduan%';

-- Mencari judul yang mengandung kata 'Docker' di mana saja
SELECT id, judul 
FROM posts 
WHERE judul LIKE '%Docker%';

-- Pencarian Case-Insensitive khas PostgreSQL (ILIKE)
-- Akan cocok dengan 'sql', 'SQL', 'Sql', dll.
SELECT id, judul 
FROM posts 
WHERE judul ILIKE '%sql%';
Catatan Performa: Perintah LIKE '%pola%' (dengan wildcard di depan) tidak bisa menggunakan Indeks B-Tree biasa. Jika tabel kamu memiliki jutaan baris, query ini akan memaksa database melakukan Sequential Scan (membaca seluruh isi tabel dari awal sampai akhir). Untuk pencarian teks berskala besar di PostgreSQL, gunakan Full-Text Search atau indeks GIN/Trigram.

4. Jebakan Paling Sering: Memahami Nilai NULL dan Three-Valued Logic

Banyak bug misterius pada aplikasi backend bersumber dari ketidakfahaman developer terhadap konsep NULL di dalam SQL.

Nilai NULL BUKAN Nol atau String Kosong

NULL di dalam SQL menandakan ketidakadaan nilai (unknown/absence of value). Karena NULL melambangkan sesuatu yang "tidak diketahui", kamu TIDAK BISA membandingkannya menggunakan operator perbandingan biasa seperti = atau !=.

SQL
-- SALAH! Query ini TIDAK AKAN mengembalikan data apapun (selalu bernilai FALSE)
SELECT * FROM users WHERE nomor_telepon = NULL;
SELECT * FROM users WHERE nomor_telepon != NULL;
Dalam sistem logika SQL (Three-Valued Logic: TRUE, FALSE, UNKNOWN), ekspresi NULL = NULL menghasilkan nilai UNKNOWN.

Cara Benar Memeriksa NULL

Gunakan operator khusus IS NULL atau IS NOT NULL:

SQL
-- BENAR: Mengambil user yang BELUM mengisi nomor telepon
SELECT id, username, nomor_telepon 
FROM users 
WHERE nomor_telepon IS NULL;

-- BENAR: Mengambil user yang SUDAH mengisi nomor telepon
SELECT id, username, nomor_telepon 
FROM users 
WHERE nomor_telepon IS NOT NULL;

Fungsi Penanganan NULL: COALESCE

PostgreSQL menyediakan fungsi bawaan COALESCE() yang sangat berguna untuk memberikan nilai fallback (default) jika suatu kolom bernilai NULL.

SQL
-- Jika nomor_telepon NULL, tampilkan teks 'Belum diisi'
SELECT 
    username, 
    COALESCE(nomor_telepon, 'Belum diisi') AS kontak_telepon 
FROM users;

5. Ringkasan & Lembar Latihan Mandiri

Memahami cara kerja SELECT dan WHERE secara presisi adalah fondasi sebelum kita belajar menggabungkan data antar tabel (JOIN) atau melakukan pengelompokan data (GROUP BY).

Cheatsheet Operator Filtering:

Operator Fungsi Contoh Kasus
= / != Perbandingan presisi status = 'published'
IN (...) Memeriksa nilai dalam daftar id IN (1, 2, 3)
BETWEEN a AND b Memeriksa rentang nilai/tanggal harga BETWEEN 10000 AND 50000
ILIKE '%...%' Pencarian teks (case-insensitive) judul ILIKE '%tutorial%'
IS NULL Memeriksa nilai kosong/absen deleted_at IS NULL


🛠️ Latihan Mandiri:

Cobalah tulis query untuk skenario berikut pada database yang sudah kita buat:

  1. Tampilkan kolom id, judul, dan status dari tabel posts yang dibuat oleh user_id = 1 DAN statusnya BUKAN 'draft'.
  2. Tampilkan semua username dari tabel users yang mengandung kata 'dev' atau 'coder' (bebas huruf besar/kecil).
  3. Tampilkan artikel yang mengandung kata 'Tips' pada judulnya ATAU dibuat setelah tanggal 15 November 2025.

Langkah Selanjutnya

Sekarang kamu sudah bisa mengekstraksi dan memfilter data spesifik sesuai kebutuhan bisnis aplikasi kamu. Namun, data yang ditarik sering kali berantakan urutannya dan terlalu banyak untuk ditampilkan sekaligus dalam satu halaman aplikasi.

Pada Artikel 3: Sorting, Limiting, dan Fungsi Agregat, kita akan mempelajari cara mengurutkan hasil data (ORDER BY), membatasi jumlah baris untuk fitur pagination (LIMIT & OFFSET), serta menghitung statistik data (COUNT, SUM, AVG, GROUP BY).
 
Sigit Wasis Subekti

Sigit Wasis Subekti

Software Engineer & Tech Educator

Software Engineer and Tech Educator sharing insights on web development and software architecture.