Klausa WHERE dari chapter sebelumnya baru memakai satu jenis kondisi: =. Dalam bahasa sehari-hari kita juga bertanya “yang harganya di bawah lima ribu”, “bukan kategori Kertas”, atau “tanggal sesudah Februari” — semuanya butuh operator perbandingan yang berbeda. MySQL menyediakan enam operator inti yang bekerja pada angka, teks, dan tanggal sekaligus. Pada chapter ini kita akan menguji keenam operator tersebut satu per satu, membuktikan bahwa perbandingan teks bawaan MySQL tidak membedakan huruf besar-kecil, lalu membongkar perilaku paling mengejutkan: membandingkan NULL dengan operator apa pun tidak menghasilkan error, melainkan hasil kosong.

Menyiapkan Tabel Latihan #

Kita pakai kembali pola data toko alat tulis. Chapter ini membutuhkan tiga tabel: produk untuk perbandingan angka dan teks, pesanan untuk perbandingan tanggal, serta pelanggan yang kolom telepon-nya sengaja dibiarkan NULL pada sebagian baris sebagai bahan uji:

sql
DROP DATABASE IF EXISTS belajar_filter;
CREATE DATABASE belajar_filter;
USE belajar_filter;

Output yang Dihasilkan:

text
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 1 row affected (0.00 sec)

Database changed
sql
CREATE TABLE produk (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nama VARCHAR(100) NOT NULL,
  kategori VARCHAR(50) NOT NULL,
  harga DECIMAL(10,2) NOT NULL,
  stok INT NOT NULL DEFAULT 0
);

INSERT INTO produk (nama, kategori, harga, stok) VALUES
  ('Buku Tulis Sidu 38', 'Alat Tulis', 4500.00, 120),
  ('Pensil 2B', 'Alat Tulis', 3000.00, 200),
  ('Penghapus Putih', 'Alat Tulis', 2500.00, 150),
  ('Pulpen Gel Hitam', 'Alat Tulis', 5000.00, 80),
  ('Spidol Permanen', 'Alat Tulis', 10000.00, 45),
  ('Kertas HVS A4', 'Kertas', 27500.00, 20),
  ('Kertas Origami', 'Kertas', 12000.00, 60),
  ('Amplop Coklat', 'Kertas', 800.00, 300),
  ('Stipo 12 Gram', 'Perekat', 6000.00, 0),
  ('Selotip Bening', 'Perekat', 8000.00, 55);

Output yang Dihasilkan:

text
Query OK, 0 rows affected (0.00 sec)

Query OK, 10 rows affected (0.00 sec)
Records: 10  Duplicates: 0  Warnings: 0
sql
CREATE TABLE pelanggan (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nama VARCHAR(100) NOT NULL,
  kota VARCHAR(50) NOT NULL,
  telepon VARCHAR(20) NULL
);

INSERT INTO pelanggan (nama, kota, telepon) VALUES
  ('Budi Santoso', 'Bandung', '0812-5000-1001'),
  ('Siti Rahayu', 'Jakarta', '0813-5000-1002'),
  ('Andi Wijaya', 'Surabaya', NULL),
  ('Dewi Lestari', 'Bandung', '0815-5000-1004'),
  ('Rian Hidayat', 'Yogyakarta', NULL),
  ('Maya Putri', 'Medan', '0817-5000-1006'),
  ('Eko Prasetyo', 'Semarang', NULL),
  ('Fitri Handayani', 'Bandung', '0819-5000-1008');

Output yang Dihasilkan:

text
Query OK, 0 rows affected (0.00 sec)

Query OK, 8 rows affected (0.00 sec)
Records: 8  Duplicates: 0  Warnings: 0
sql
CREATE TABLE pesanan (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nama_pelanggan VARCHAR(100) NOT NULL,
  nama_produk VARCHAR(100) NOT NULL,
  jumlah INT NOT NULL,
  total DECIMAL(10,2) NOT NULL,
  tanggal DATE NOT NULL
);

INSERT INTO pesanan (nama_pelanggan, nama_produk, jumlah, total, tanggal) VALUES
  ('Budi Santoso', 'Pensil 2B', 10, 30000.00, '2026-01-05'),
  ('Siti Rahayu', 'Kertas HVS A4', 2, 55000.00, '2026-01-18'),
  ('Dewi Lestari', 'Spidol Permanen', 3, 30000.00, '2026-02-01'),
  ('Budi Santoso', 'Kertas Origami', 5, 60000.00, '2026-02-14'),
  ('Maya Putri', 'Buku Tulis Sidu 38', 20, 90000.00, '2026-02-28'),
  ('Eko Prasetyo', 'Pulpen Gel Hitam', 4, 20000.00, '2026-03-05'),
  ('Fitri Handayani', 'Selotip Bening', 6, 48000.00, '2026-03-12'),
  ('Budi Santoso', 'Penghapus Putih', 12, 30000.00, '2026-03-25'),
  ('Budi Santoso', 'Pulpen Gel Hitam', 2, 10000.00, '2026-03-25');

Output yang Dihasilkan:

text
Query OK, 0 rows affected (0.00 sec)

Query OK, 9 rows affected (0.00 sec)
Records: 9  Duplicates: 0  Warnings: 0

Enam Operator Inti #

Tabel berikut merangkum keenam operator perbandingan beserta artinya. Seluruh operator mengembalikan nilai boolean: 1 bila benar, 0 bila salah, dan NULL bila salah satu sisi belum diketahui nilainya.

OperatorArtiContoh kondisi
=sama denganharga = 5000
<> atau !=tidak sama dengankategori <> 'Kertas'
<kurang daristok < 50
<=kurang dari atau sama denganharga <= 5000
>lebih dariharga > 10000
>=lebih dari atau sama denganharga >= 10000

Kita mulai dari operator = yang sudah kita kenal, lalu pasangannya <>:

sql
SELECT nama, kategori
FROM produk
WHERE kategori = 'Perekat'
ORDER BY id;

Output yang Dihasilkan:

text
+----------------+----------+
| nama           | kategori |
+----------------+----------+
| Stipo 12 Gram  | Perekat  |
| Selotip Bening | Perekat  |
+----------------+----------+
2 rows in set (0.00 sec)
sql
SELECT nama, kategori
FROM produk
WHERE kategori <> 'Alat Tulis'
ORDER BY id;

Output yang Dihasilkan:

text
+----------------+----------+
| nama           | kategori |
+----------------+----------+
| Kertas HVS A4  | Kertas   |
| Kertas Origami | Kertas   |
| Amplop Coklat  | Kertas   |
| Stipo 12 Gram  | Perekat  |
| Selotip Bening | Perekat  |
+----------------+----------+
5 rows in set (0.00 sec)

Kondisi pertama meloloskan dua produk Perekat, sedangkan kondisi kedua membaliknya menjadi lima produk di luar Alat Tulis. Operator != memiliki arti yang persis sama dengan <>; keduanya sama-sama valid di MySQL 8.4, seperti bukti berikut:

sql
SELECT 5 != 5 AS pakai_seru, 5 <> 5 AS pakai_lebih_kecil;

Output yang Dihasilkan:

text
+------------+-------------------+
| pakai_seru | pakai_lebih_kecil |
+------------+-------------------+
|          0 |                 0 |
+------------+-------------------+
1 row in set (0.00 sec)

Perbandingan pada Angka #

Empat operator sisanya paling natural dipakai pada kolom angka. Query berikut mengambil produk dengan harga paling banyak 5000:

sql
SELECT nama, harga
FROM produk
WHERE harga <= 5000
ORDER BY harga;

Output yang Dihasilkan:

text
+--------------------+---------+
| nama               | harga   |
+--------------------+---------+
| Amplop Coklat      |  800.00 |
| Penghapus Putih    | 2500.00 |
| Pensil 2B          | 3000.00 |
| Buku Tulis Sidu 38 | 4500.00 |
| Pulpen Gel Hitam   | 5000.00 |
+--------------------+---------+
5 rows in set (0.00 sec)

Lima produk lolos, dan perhatikan bahwa Pulpen Gel Hitam dengan harga tepat 5000 ikut di dalam hasil — inilah makna tanda sama dengan pada operator <=. Bandingkan dengan dua operator ketat berikut:

sql
SELECT nama, harga
FROM produk
WHERE harga > 10000
ORDER BY harga;

Output yang Dihasilkan:

text
+----------------+----------+
| nama           | harga    |
+----------------+----------+
| Kertas Origami | 12000.00 |
| Kertas HVS A4  | 27500.00 |
+----------------+----------+
2 rows in set (0.00 sec)
sql
SELECT nama, harga
FROM produk
WHERE harga >= 10000
ORDER BY harga;

Output yang Dihasilkan:

text
+-----------------+----------+
| nama            | harga    |
+-----------------+----------+
| Spidol Permanen | 10000.00 |
| Kertas Origami  | 12000.00 |
| Kertas HVS A4   | 27500.00 |
+-----------------+----------+
3 rows in set (0.00 sec)

Query pertama meloloskan dua produk di atas 10000, sedangkan query kedua meloloskan tiga produk karena Spidol Permanen yang harganya tepat 10000 kini ikut. Selisih satu karakter pada operator bisa mengubah isi hasil — saat menulis query laporan, pastikan keputusan “batas termasuk atau tidak” memang disengaja.

Perbandingan pada Teks #

Perbandingan teks menyimpan kejutan pertama: secara bawaan, MySQL tidak membedakan huruf besar dan kecil. Kita buktikan dengan literal sebelum memakainya di WHERE:

sql
SELECT 'Kopi' = 'kopi' AS hasil_sama;

Output yang Dihasilkan:

text
+------------+
| hasil_sama |
+------------+
|          1 |
+------------+
1 row in set (0.00 sec)

Perbandingan 'Kopi' = 'kopi' mengembalikan 1 (benar). Perilaku ini berasal dari collation bawaan server:

sql
SELECT @@collation_server AS collation_bawaan;

Output yang Dihasilkan:

text
+--------------------+
| collation_bawaan   |
+--------------------+
| utf8mb4_0900_ai_ci |
+--------------------+
1 row in set (0.00 sec)

Nama collation utf8mb4_0900_ai_ci bisa dibaca sebagai spesifikasi: _ai berarti accent insensitive (huruf beraksen dianggap sama dengan tanpa aksen) dan _ci berarti case insensitive (besar-kecil diabaikan). Akibatnya, kondisi berikut menemukan produk Kertas walaupun penulisannya kita kecilkan semua:

sql
SELECT nama, kategori
FROM produk
WHERE kategori = 'kertas'
ORDER BY id;

Output yang Dihasilkan:

text
+----------------+----------+
| nama           | kategori |
+----------------+----------+
| Kertas HVS A4  | Kertas   |
| Kertas Origami | Kertas   |
| Amplop Coklat  | Kertas   |
+----------------+----------+
3 rows in set (0.00 sec)

Tiga produk kategori Kertas tetap ditemukan. Bila kita benar-benar membutuhkan perbandingan yang membedakan huruf besar-kecil, operator BINARY memaksa perbandingan byte per byte:

sql
SELECT BINARY 'Kopi' = 'kopi' AS hasil_biner;

Output yang Dihasilkan:

text
+-------------+
| hasil_biner |
+-------------+
|           0 |
+-------------+
1 row in set, 1 warning (0.00 sec)

Perbandingan pada Tanggal #

Tanggal dibandingkan secara kronologis dengan literal format 'YYYY-MM-DD'. Kondisi tanggal < '2026-02-01' berarti “tercatat sebelum 1 Februari 2026”:

sql
SELECT id, nama_pelanggan, tanggal
FROM pesanan
WHERE tanggal < '2026-02-01'
ORDER BY id;

Output yang Dihasilkan:

text
+----+----------------+------------+
| id | nama_pelanggan | tanggal    |
+----+----------------+------------+
|  1 | Budi Santoso   | 2026-01-05 |
|  2 | Siti Rahayu    | 2026-01-18 |
+----+----------------+------------+
2 rows in set (0.00 sec)
sql
SELECT id, nama_pelanggan, nama_produk
FROM pesanan
WHERE tanggal = '2026-02-01';

Output yang Dihasilkan:

text
+----+----------------+-----------------+
| id | nama_pelanggan | nama_produk     |
+----+----------------+-----------------+
|  3 | Dewi Lestari   | Spidol Permanen |
+----+----------------+-----------------+
1 row in set (0.00 sec)

Dua pesanan Januari lolos pada query pertama, dan satu pesanan tepat di 1 Februari ditemukan query kedua. Operator <, <=, >, >= bekerja sama persis seperti pada angka — hanya saja “lebih besar” berarti “lebih baru” pada konteks tanggal.

Saat NULL Bertemu Operator Perbandingan #

Kini bagian yang sering menjebak pemula. Tiga pelanggan pada tabel kita tidak punya nomor telepon — nilainya NULL, yang berarti “tidak diketahui”, bukan teks kosong. Kita coba bandingkan NULL langsung:

sql
SELECT NULL = NULL AS cek_sama, NULL <> 5 AS cek_beda;

Output yang Dihasilkan:

text
+----------+----------+
| cek_sama | cek_beda |
+----------+----------+
|     NULL |     NULL |
+----------+----------+
1 row in set (0.00 sec)

Hasilnya bukan 1, bukan 0, melainkan NULL untuk keduanya. Logikanya: “tidak diketahui sama dengan tidak diketahui” tidak bisa dipastikan benar maupun salah, jadi jawabannya tetap tidak diketahui. Konsekuensinya di klausa WHERE sangat nyata:

sql
SELECT nama, telepon
FROM pelanggan
WHERE telepon = NULL;

Output yang Dihasilkan:

text
Empty set (0.00 sec)

Tidak ada error yang terjadi — query berjalan mulus, tetapi hasilnya kosong. Baris dengan telepon berisi NULL tidak pernah bernilai benar pada telepon = NULL, dan baris dengan nomor telepon juga bernilai salah, sehingga tidak ada satu pun baris yang lolos. MySQL menyediakan operator khusus <=> (NULL-safe equal) yang memperlakukan dua NULL sebagai sama:

sql
SELECT 5 = NULL AS pembanding_biasa, 5 <=> NULL AS pembanding_aman_null;

Output yang Dihasilkan:

text
+------------------+----------------------+
| pembanding_biasa | pembanding_aman_null |
+------------------+----------------------+
|             NULL |                    0 |
+------------------+----------------------+
1 row in set (0.00 sec)

Operator <=> mengembalikan 0 untuk 5 <=> NULL (nilai berbeda dengan yang tidak diketahui) dan mengembalikan 1 bila kedua sisi sama-sama NULL. Untuk memeriksa NULL secara mudah dibaca, MySQL juga menyediakan kondisi IS NULL yang akan kita bahas tuntas di chapter Is NULL.

Membersihkan Database Latihan #

Perbandingan kita sudah lengkap. Tiga tabel latihan dijatuhkan bersama database-nya:

sql
DROP DATABASE belajar_filter;

Output yang Dihasilkan:

text
Query OK, 3 rows affected (0.00 sec)

Nilai 3 rows affected sesuai jumlah tabel yang terhapus: produk, pelanggan, dan pesanan.

Referensi #

Enam operator perbandingan kini menjadi kosakata lengkap kita. Kondisi nyata jarang berdiri sendiri — “kategori Alat Tulis dan harga di bawah lima ribu atau stok habis” menggabungkan beberapa kondisi sekaligus. Chapter berikutnya memperkenalkan operator logika AND, OR, dan NOT yang merangkai kondisi-kondisi tersebut menjadi satu keputusan akhir.