Klausa WHERE dari chapter sebelumnya menyaring baris lewat kondisi, dan hampir semua kondisi dibangun dari satu bata yang sama: operator perbandingan. harga > 20000, kategori = 'kertas', tanggal_masuk >= DATE '2026-01-01' — semuanya memakai operator yang mengembalikan nilai boolean dari dua nilai yang dibandingkan. Pada chapter ini kita membahas ketujuh operator itu satu per satu, lalu melihat bagaimana perilakunya berbeda untuk angka, tanggal, timestamp, dan teks — termasuk satu aturan emas yang membingkai semuanya: perbandingan dengan NULL tidak pernah menghasilkan true ataupun false.

Tujuh Operator Perbandingan #

PostgreSQL menyediakan tujuh operator perbandingan dasar. Tabel berikut merangkum semuanya beserta contoh kondisi yang bernilai true untuk baris Kertas HVS A4 (harga 55000, kategori kertas):

OperatorArtiContoh
=sama dengankategori = 'kertas'
<>tidak sama dengan (bentuk standar SQL)kategori <> 'alat tulis'
!=tidak sama dengan (bentuk lain dari <>)kategori != 'alat tulis'
<kurang dariharga < 100000
<=kurang dari atau sama denganharga <= 55000
>lebih dariharga > 50000
>=lebih dari atau sama denganharga >= 55000

Dua operator “tidak sama dengan” itu identik sepenuhnya — <> adalah bentuk yang dianjurkan standar SQL, sedangkan != adalah bentuk populer yang juga diterima PostgreSQL. Keduanya boleh dipakai bergantian, tetapi konsistensi dalam satu tim lebih penting daripada pilihan bentuknya. Tabel latihan kita masih sama — produk milik Toko Maju Jaya — ditambah satu tabel kecil penyesuaian_stok yang mencatat koreksi stok beserta waktu kejadiannya:

sql buat-tabel.sql
CREATE TABLE produk (
    id            integer PRIMARY KEY,
    nama          text NOT NULL,
    kategori      text NOT NULL,
    harga         numeric(10, 2) NOT NULL,
    stok          integer NOT NULL,
    aktif         boolean NOT NULL,
    tanggal_masuk date,
    promo         text
);

INSERT INTO produk (id, nama, kategori, harga, stok, aktif, tanggal_masuk, promo) VALUES
    (1, 'Buku Tulis 58',    'alat tulis', 4500,   120, true,  DATE '2025-11-10', NULL),
    (2, 'Pulpen Hitam',     'alat tulis', 3000,   200, true,  DATE '2025-12-01', 'Diskon 10%'),
    (3, 'Kertas HVS A4',    'kertas',     55000,   40, true,  DATE '2026-01-05', 'Diskon 50%'),
    (4, 'Stapler Besar',    'alat tulis', 24000,   15, false, DATE '2026-01-20', NULL),
    (5, 'Amplop Coklat',    'kertas',     1500,  500, true,  DATE '2026-02-14', NULL),
    (6, 'Penghapus',        'alat tulis', 2000,    0, false, DATE '2026-02-14', NULL),
    (7, 'Kalkulator Solar', 'elektronik', 185000,   8, true,  DATE '2026-03-02', 'Diskon 25%'),
    (8, 'Penggaris 30cm',   'alat tulis', 3500,   85, true,  DATE '2026-03-15', 'Diskon 5%');

CREATE TABLE penyesuaian_stok (
    id        integer PRIMARY KEY,
    produk_id integer NOT NULL,
    perubahan integer NOT NULL,
    waktu     timestamp NOT NULL
);

INSERT INTO penyesuaian_stok (id, produk_id, perubahan, waktu) VALUES
    (1, 3, -10, TIMESTAMP '2026-01-15 08:30:00'),
    (2, 3,   5, TIMESTAMP '2026-01-15 15:45:00'),
    (3, 7,  -2, TIMESTAMP '2026-02-02 09:10:00'),
    (4, 1,  50, TIMESTAMP '2026-03-20 16:00:00');

Output yang Dihasilkan:

text
CREATE TABLE
INSERT 0 8
CREATE TABLE
INSERT 0 4

Sama Dengan dan Tidak Sama Dengan #

Operator = meloloskan baris yang nilainya persis sama; <> dan != kebalikannya. Tiga perintah berikut memakai ketiganya pada kolom kategori:

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

SELECT id, nama, kategori FROM produk
WHERE kategori <> 'alat tulis'
ORDER BY id;

SELECT id, nama, kategori FROM produk
WHERE kategori != 'alat tulis'
ORDER BY id;

Output yang Dihasilkan:

text
 id |       nama       |  kategori  
----+------------------+------------
  7 | Kalkulator Solar | elektronik
(1 row)

 id |       nama       |  kategori  
----+------------------+------------
  3 | Kertas HVS A4    | kertas
  5 | Amplop Coklat    | kertas
  7 | Kalkulator Solar | elektronik
(3 rows)

 id |       nama       |  kategori  
----+------------------+------------
  3 | Kertas HVS A4    | kertas
  5 | Amplop Coklat    | kertas
  7 | Kalkulator Solar | elektronik
(3 rows)

Perintah pertama hanya menjaring Kalkulator Solar — satu-satunya produk elektronik. Perintah kedua dan ketiga mengembalikan hasil yang persis sama: tiga produk yang kategorinya bukan alat tulis (Kertas HVS A4, Amplop Coklat, Kalkulator Solar). Identitas hasil itu bukan kebetulan; <> dan != adalah operator yang sama persis, cukup pilih satu sebagai kebiasaan.

Perhatikan juga perbandingan teks bersifat case-sensitive: kategori = 'Kertas' tidak akan cocok dengan 'kertas' karena huruf besar-kecilnya ikut dibandingkan. Perilaku ini dan cara menyiasatinya dibahas di chapter LIKE dan ILIKE.

Membandingkan Angka #

Empat operator urutan (<, <=, >, >=) bekerja seperti matematika sekolah. Satu hal yang perlu diperhatikan: hasil ORDER BY di bawah sengaja memakai kolom yang dibandingkan, sehingga kita bisa melihat posisi batas dengan jelas:

SELECT id, nama, harga FROM produk
WHERE harga >= 24000
ORDER BY harga, id;

SELECT id, nama, harga FROM produk
WHERE harga > 100000
ORDER BY harga, id;

SELECT id, nama, stok FROM produk
WHERE stok <= 15
ORDER BY stok, id;

SELECT id, nama, stok FROM produk
WHERE stok < 10
ORDER BY stok, id;

Output yang Dihasilkan:

text
 id |       nama       |   harga   
----+------------------+-----------
  4 | Stapler Besar    |  24000.00
  3 | Kertas HVS A4    |  55000.00
  7 | Kalkulator Solar | 185000.00
(3 rows)

 id |       nama       |   harga   
----+------------------+-----------
  7 | Kalkulator Solar | 185000.00
(1 row)

 id |       nama       | stok 
----+------------------+------
  6 | Penghapus        |    0
  7 | Kalkulator Solar |    8
  4 | Stapler Besar    |   15
(3 rows)

 id |       nama       | stok 
----+------------------+------
  6 | Penghapus        |    0
  7 | Kalkulator Solar |    8
(2 rows)

Bedah empat hasil tersebut:

  1. harga >= 24000 menjaring tiga produk, termasuk Stapler Besar yang harganya tepat 24000 — operator >= meloloskan nilai yang sama dengan batas.
  2. harga > 100000 hanya menjaring Kalkulator Solar; Kertas HVS A4 (55000) tidak lolos karena 55000 tidak lebih dari 100000.
  3. stok <= 15 menjaring tiga produk dengan stok paling tipis, termasuk Stapler Besar yang tepat 15.
  4. stok < 10 menjaring dua produk — Stapler Besar (15) kini gugur karena 15 tidak kurang dari 10. Selisih satu karakter (<= vs <) mengubah hasil dua menjadi tiga baris; itulah alasan membaca operator dengan teliti.

Membandingkan Tanggal dan Timestamp #

Tanggal dan timestamp dibandingkan secara kronologis — tanggal yang lebih awal selalu “kurang dari” tanggal yang lebih baru. Literalnya ditulis dengan awalan DATE atau TIMESTAMP dan nilai tetap dalam format ISO, sehingga hasilnya tidak bergantung pada setting regional server:

SELECT id, nama, tanggal_masuk FROM produk
WHERE tanggal_masuk > DATE '2026-02-01'
ORDER BY tanggal_masuk, id;

SELECT id, produk_id, perubahan, waktu FROM penyesuaian_stok
WHERE waktu >= TIMESTAMP '2026-01-15 09:00:00'
ORDER BY waktu, id;

SELECT id, produk_id, perubahan, waktu FROM penyesuaian_stok
WHERE waktu < TIMESTAMP '2026-02-01'
ORDER BY waktu, id;

Output yang Dihasilkan:

text
 id |       nama       | tanggal_masuk 
----+------------------+---------------
  5 | Amplop Coklat    | 2026-02-14
  6 | Penghapus        | 2026-02-14
  7 | Kalkulator Solar | 2026-03-02
  8 | Penggaris 30cm   | 2026-03-15
(4 rows)

 id | produk_id | perubahan |        waktu        
----+-----------+-----------+---------------------
  2 |         3 |         5 | 2026-01-15 15:45:00
  3 |         7 |        -2 | 2026-02-02 09:10:00
  4 |         1 |        50 | 2026-03-20 16:00:00
(3 rows)

 id | produk_id | perubahan |        waktu        
----+-----------+-----------+---------------------
  1 |         3 |       -10 | 2026-01-15 08:30:00
  2 |         3 |         5 | 2026-01-15 15:45:00
(2 rows)

Perintah pertama menjaring empat produk yang masuk setelah 1 Februari 2026. Dua perintah berikutnya bekerja pada kolom timestamp: perbandingan waktu >= TIMESTAMP '2026-01-15 09:00:00' menjaring tiga penyesuaian, dan yang menarik adalah penyesuaian pertama (pukul 08:30) yang tersaring keluar — timestamp membandingkan sampai level detik, bahkan mikrodetik, sehingga pukul 08:30 jelas lebih kecil daripada 09:00. Perintah ketiga memperlihatkan sisi sebaliknya: dua penyesuaian bulan Januari lolos karena terjadi sebelum 1 Februari.

Membandingkan Teks: Urutan Kamus #

Operator < dan > pada teks memakai urutan kamus (lexicographic) — perbandingan karakter demi karakter dari kiri. Kata yang lebih pendek yang menjadi awalan kata lain selalu lebih kecil, sama seperti di kamus: Stapler muncul sebelum Stapler Besar. Namun ada detail yang sering mengejutkan: di server ini (locale C), huruf besar dibandingkan sebagai byte yang lebih kecil daripada huruf kecil:

SELECT id, nama FROM produk
WHERE nama < 'Penghapus'
ORDER BY nama;

SELECT id, nama FROM produk
WHERE nama >= 'P'
ORDER BY nama;

SELECT 'Makanan' < 'minuman' AS huruf_besar_dulu,
       'a' < 'A' AS a_vs_A,
       'Stapler' < 'Stapler Besar' AS prefiks_lebih_pendek;

Output yang Dihasilkan:

text
 id |       nama       
----+------------------
  5 | Amplop Coklat
  1 | Buku Tulis 58
  7 | Kalkulator Solar
  3 | Kertas HVS A4
  8 | Penggaris 30cm
(5 rows)

 id |      nama      
----+----------------
  8 | Penggaris 30cm
  6 | Penghapus
  2 | Pulpen Hitam
  4 | Stapler Besar
(4 rows)

 huruf_besar_dulu | a_vs_a | prefiks_lebih_pendek 
------------------+--------+----------------------
 t                | f      | t
(1 row)

Mari kita bedah tiga hasil itu:

  1. nama < 'Penghapus' menjaring lima produk yang urut kamusnya sebelum kata “Penghapus” — termasuk Penggaris 30cm, karena Pengg... lebih kecil daripada Pengh... (huruf g sebelum h). Bandingkan kamus sungguhan: “penggaris” memang tercantum sebelum “penghapus”.
  2. nama >= 'P' menjaring empat produk: tiga yang berawalan P (Pulpen Hitam, Penghapus, Penggaris 30cm) plus Stapler Besar yang lolos karena awalan S memang lebih besar daripada P di urutan kamus. Perhatikan juga bahwa setiap kata berawalan P dinilai lebih besar daripada satu huruf P — kata yang lebih panjang dengan awalan sama selalu lebih besar.
  3. Baris kebenaran terakhir membuktikan tiga aturan sekaligus: 'Makanan' < 'minuman' karena M (byte lebih kecil) mengalah sebelum a vs i dibandingkan; 'a' < 'A' bernilai false karena huruf kecil punya byte lebih besar; dan 'Stapler' < 'Stapler Besar' karena prefiks yang lebih pendek selalu lebih dulu.

Perbandingan dengan NULL Selalu NULL #

Aturan terpenting sebelum melangkah lebih jauh: NULL bukan nilai, melainkan penanda “tidak ada nilai”. Operator perbandingan apa pun yang menyentuh NULL menghasilkan NULL, bukan true atau false. Ekspresi 5000 > NULL ibarat ditanya “apakah lima ribu lebih besar dari sesuatu yang tidak diketahui nilainya?” — jawaban yang jujur memang “tidak bisa dipastikan”:

SELECT 5000 > NULL AS angka_dibanding_null,
       'kertas' = NULL AS teks_dibanding_null;

SELECT count(*) AS baris_yang_lolos
FROM produk
WHERE harga > NULL;

Output yang Dihasilkan:

text
 angka_dibanding_null | teks_dibanding_null 
----------------------+---------------------
                      | 
(1 row)

 baris_yang_lolos 
------------------
                0
(1 row)

Dua kolom pada baris pertama tampil kosong — itulah psql menampilkan NULL; bukan false, bukan true. Konsekuensinya di WHERE sangat nyata: WHERE harga > NULL mengembalikan nol baris tanpa pesan error apa pun, meski harga delapan baris semuanya terisi. WHERE hanya meloloskan baris yang kondisinya true; NULL tidak pernah true, jadi barisnya dibuang — perilaku yang sama dengan jebakan promo != 'Diskon 50%' di chapter WHERE.

Ketujuh operator perbandingan kini lengkap di tangan kita: sama dengan, tidak sama dengan, dan empat operator urutan untuk angka, tanggal, timestamp, maupun teks. Kondisi nyata di aplikasi jarang sesederhana itu — “produk aktif dan harga di bawah lima ribu”, “kategori kertas atau elektronik” — dan untuk menggabungkan kondisi itulah PostgreSQL menyediakan operator logika AND, OR, dan NOT, materi chapter berikutnya.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

banding-tanggal.sql

Unduh berkas
sql
SELECT id, nama, tanggal_masuk FROM produk
WHERE tanggal_masuk > DATE '2026-02-01'
ORDER BY tanggal_masuk, id;

SELECT id, produk_id, perubahan, waktu FROM penyesuaian_stok
WHERE waktu >= TIMESTAMP '2026-01-15 09:00:00'
ORDER BY waktu, id;

SELECT id, produk_id, perubahan, waktu FROM penyesuaian_stok
WHERE waktu < TIMESTAMP '2026-02-01'
ORDER BY waktu, id;

banding-teks.sql

Unduh berkas
sql
SELECT id, nama FROM produk
WHERE nama < 'Penghapus'
ORDER BY nama;

SELECT id, nama FROM produk
WHERE nama >= 'P'
ORDER BY nama;

SELECT 'Makanan' < 'minuman' AS huruf_besar_dulu,
       'a' < 'A' AS a_vs_A,
       'Stapler' < 'Stapler Besar' AS prefiks_lebih_pendek;

buat-tabel.sql

Unduh berkas
sql
CREATE TABLE produk (
    id            integer PRIMARY KEY,
    nama          text NOT NULL,
    kategori      text NOT NULL,
    harga         numeric(10, 2) NOT NULL,
    stok          integer NOT NULL,
    aktif         boolean NOT NULL,
    tanggal_masuk date,
    promo         text
);

INSERT INTO produk (id, nama, kategori, harga, stok, aktif, tanggal_masuk, promo) VALUES
    (1, 'Buku Tulis 58',    'alat tulis', 4500,   120, true,  DATE '2025-11-10', NULL),
    (2, 'Pulpen Hitam',     'alat tulis', 3000,   200, true,  DATE '2025-12-01', 'Diskon 10%'),
    (3, 'Kertas HVS A4',    'kertas',     55000,   40, true,  DATE '2026-01-05', 'Diskon 50%'),
    (4, 'Stapler Besar',    'alat tulis', 24000,   15, false, DATE '2026-01-20', NULL),
    (5, 'Amplop Coklat',    'kertas',     1500,  500, true,  DATE '2026-02-14', NULL),
    (6, 'Penghapus',        'alat tulis', 2000,    0, false, DATE '2026-02-14', NULL),
    (7, 'Kalkulator Solar', 'elektronik', 185000,   8, true,  DATE '2026-03-02', 'Diskon 25%'),
    (8, 'Penggaris 30cm',   'alat tulis', 3500,   85, true,  DATE '2026-03-15', 'Diskon 5%');

CREATE TABLE penyesuaian_stok (
    id        integer PRIMARY KEY,
    produk_id integer NOT NULL,
    perubahan integer NOT NULL,
    waktu     timestamp NOT NULL
);

INSERT INTO penyesuaian_stok (id, produk_id, perubahan, waktu) VALUES
    (1, 3, -10, TIMESTAMP '2026-01-15 08:30:00'),
    (2, 3,   5, TIMESTAMP '2026-01-15 15:45:00'),
    (3, 7,  -2, TIMESTAMP '2026-02-02 09:10:00'),
    (4, 1,  50, TIMESTAMP '2026-03-20 16:00:00');

null-perbandingan.sql

Unduh berkas
sql
SELECT 5000 > NULL AS angka_dibanding_null,
       'kertas' = NULL AS teks_dibanding_null;

SELECT count(*) AS baris_yang_lolos
FROM produk
WHERE harga > NULL;

operator-sama.sql

Unduh berkas
sql
SELECT id, nama, kategori FROM produk
WHERE kategori = 'elektronik'
ORDER BY id;

SELECT id, nama, kategori FROM produk
WHERE kategori <> 'alat tulis'
ORDER BY id;

SELECT id, nama, kategori FROM produk
WHERE kategori != 'alat tulis'
ORDER BY id;

urutan-angka.sql

Unduh berkas
sql
SELECT id, nama, harga FROM produk
WHERE harga >= 24000
ORDER BY harga, id;

SELECT id, nama, harga FROM produk
WHERE harga > 100000
ORDER BY harga, id;

SELECT id, nama, stok FROM produk
WHERE stok <= 15
ORDER BY stok, id;

SELECT id, nama, stok FROM produk
WHERE stok < 10
ORDER BY stok, id;