EXISTS SQL: Cek Keberadaan Data Lebih Cepat dari IN
Blog/Tutorial SQL/EXISTS SQL: Cek Keberadaan Data Lebih Cepat dari IN

EXISTS SQL: Cek Keberadaan Data Lebih Cepat dari IN

BimaBima
·21 Februari 2026·9 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

TL;DR

EXISTS adalah operator SQL yang mengecek apakah sebuah subquery menghasilkan minimal satu baris, lalu mengembalikan TRUE atau FALSE. Begitu nemu satu baris yang cocok, dia langsung berhenti nyari, jadi biasanya lebih cepat dari IN di tabel besar. EXISTS juga aman dari jebakan NULL yang bikin NOT IN diam-diam ngasih hasil kosong. Isi SELECT di dalam EXISTS gak pernah dipakai, makanya orang biasa nulis SELECT 1 aja.

EXISTS ngecek satu hal doang: ada gak baris yang cocok? Begitu ketemu satu, dia langsung berhenti nyari.

IN gak gitu. Dia ngumpulin dulu semua nilai dari subquery, baru dibandingin satu per satu.

Di tabel 100 baris, selisihnya gak kerasa. Di tabel 5 juta baris, ini bedanya antara query 0,3 detik sama query 40 detik.

Apa itu EXISTS di SQL?

EXISTS adalah operator SQL yang mengecek apakah sebuah subquery menghasilkan minimal satu baris. Hasilnya cuma dua: TRUE kalau ada, FALSE kalau kosong.

SELECT kolom
FROM tabel_a a
WHERE EXISTS (
    SELECT 1
    FROM tabel_b b
    WHERE b.a_id = a.id
);

Perhatiin SELECT 1 di dalamnya. Itu bukan typo.

Kenapa SELECT 1, bukan SELECT *?

Soalnya isi subquery-nya gak pernah dipakai. EXISTS cuma peduli: ada barisnya atau nggak.

Kamu bisa nulis SELECT *, SELECT nama, atau bahkan SELECT 'terserah' — hasilnya identik. SELECT 1 udah jadi konvensi karena paling pendek dan langsung ngasih sinyal ke pembaca bahwa isinya gak penting.

Contoh kasus: pelanggan yang belum pernah pesan

Pakai dataset toko_berkah. Bikin tabelnya:

CREATE TABLE pelanggan (
    pelanggan_id INT PRIMARY KEY,
    nama         VARCHAR(100) NOT NULL,
    kota         VARCHAR(50)
);

CREATE TABLE pesanan (
    pesanan_id   INT PRIMARY KEY,
    pelanggan_id INT,
    tanggal      DATE,
    total        DECIMAL(12,2)
);

Isi datanya:

INSERT INTO pelanggan (pelanggan_id, nama, kota) VALUES
(1, 'Warung Bu Siti',   'Bandung'),
(2, 'Toko Pak Anwar',   'Cimahi'),
(3, 'Kios Mang Ujang',  'Soreang'),
(4, 'Warung Teh Nina',  'Bandung'),
(5, 'Toko Bu Rina',     'Cimahi');

INSERT INTO pesanan (pesanan_id, pelanggan_id, tanggal, total) VALUES
(101, 1,    '2026-01-05', 1250000),
(102, 2,    '2026-01-06',  890000),
(103, 1,    '2026-01-09',  640000),
(104, NULL, '2026-01-11',  320000);

Perhatiin pesanan 104. pelanggan_id-nya NULL — data kotor dari sistem kasir yang gagal nyimpen ID.

Ingat NULL itu. Dia bakal jadi bom waktu sebentar lagi.

Siapa yang pernah pesan?

SELECT p.pelanggan_id, p.nama, p.kota
FROM pelanggan p
WHERE EXISTS (
    SELECT 1
    FROM pesanan o
    WHERE o.pelanggan_id = p.pelanggan_id
);

Hasil: Warung Bu Siti, Toko Pak Anwar. Dua orang.

Perhatiin Bu Siti punya dua pesanan (101 dan 103), tapi cuma muncul sekali. EXISTS gak bikin baris berlipat — dia berhenti begitu nemu yang pertama.

Coba pakai JOIN. Bu Siti bakal muncul dua kali, dan kamu harus nambahin DISTINCT buat benerin.

Siapa yang belum pernah pesan?

SELECT p.pelanggan_id, p.nama, p.kota
FROM pelanggan p
WHERE NOT EXISTS (
    SELECT 1
    FROM pesanan o
    WHERE o.pelanggan_id = p.pelanggan_id
);

Hasil: Kios Mang Ujang, Warung Teh Nina, Toko Bu Rina. Tiga pelanggan.

Itu daftar orang yang perlu di-follow up tim sales besok pagi. Bener dan lengkap.

Jebakan NOT IN: kenapa hasilnya bisa kosong

Sekarang coba pertanyaan yang sama pakai NOT IN:

SELECT p.pelanggan_id, p.nama
FROM pelanggan p
WHERE p.pelanggan_id NOT IN (
    SELECT o.pelanggan_id FROM pesanan o
);

Hasilnya: 0 baris.

Bukan tiga. Nol. Padahal jelas-jelas ada tiga pelanggan yang belum pernah pesan.

Penyebabnya

Ingat pesanan 104 yang pelanggan_id-nya NULL?

Waktu SQL bandingin sebuah angka sama NULL, hasilnya bukan TRUE atau FALSE. Hasilnya UNKNOWN.

NOT IN butuh semua perbandingan bernilai TRUE buat ngeloloskan sebuah baris. Satu UNKNOWN aja, seluruh baris kebuang.

Jadi begitu ada satu NULL nyempil di subquery, NOT IN bakal ngasih hasil kosong. Tanpa error. Tanpa warning.

Ini penjelasan lengkapnya ada di artikel NULL di SQL, dan cara kerja three-valued logic-nya dibahas di dokumentasi subquery expressions PostgreSQL.

Cara benerinnya

Pilihan pertama, pakai NOT EXISTS. Dia kebal NULL, dan itu alasan utama orang milih dia.

Pilihan kedua, kalau tetep mau NOT IN, saring NULL-nya dulu:

SELECT p.pelanggan_id, p.nama
FROM pelanggan p
WHERE p.pelanggan_id NOT IN (
    SELECT o.pelanggan_id
    FROM pesanan o
    WHERE o.pelanggan_id IS NOT NULL
);

Sekarang keluar tiga baris. Tapi kamu harus inget nulis IS NOT NULL-nya tiap kali. NOT EXISTS gak nuntut kamu inget apa-apa.

EXISTS vs IN vs JOIN: kapan pakai yang mana

SituasiPakaiAlasan
Cek keberadaan, tabel besarEXISTSBerhenti di baris pertama yang cocok
Cek ketiadaan, subquery bisa punya NULLNOT EXISTSNOT IN bakal ngasih hasil kosong
Daftar nilai pendek dan pastiINLebih pendek, lebih gampang dibaca
Butuh kolom dari tabel keduaJOINEXISTS gak bisa ngambil kolom
Butuh ngitung berapa banyakJOIN + GROUP BYEXISTS cuma jawab ada atau nggak

Aturan yang aku pakai: kalau pertanyaannya "ada gak?", jawabannya EXISTS. Kalau pertanyaannya "berapa?" atau "apa aja isinya?", jawabannya JOIN.

EXISTS dengan kondisi tambahan

Kamu bisa numpuk kondisi di dalam subquery-nya:

SELECT p.nama
FROM pelanggan p
WHERE EXISTS (
    SELECT 1
    FROM pesanan o
    WHERE o.pelanggan_id = p.pelanggan_id
      AND o.total > 1000000
      AND o.tanggal >= DATE '2026-01-01'
);

Artinya: pelanggan yang punya minimal satu pesanan di atas 1 juta sejak awal 2026.

Hasilnya: Warung Bu Siti doang.

Ini pola yang susah ditiru pakai IN, soalnya IN cuma bisa bandingin satu kolom.

Kesalahan umum

1. Lupa nyambungin ke tabel luar

-- SALAH: gak ada korelasi
WHERE EXISTS (SELECT 1 FROM pesanan)

Ini TRUE buat semua baris, selama tabel pesanan gak kosong. Filternya gak ngefek sama sekali, dan kamu bakal bingung kenapa semua data keluar.

Selalu ada kondisi yang nyambungin kolom subquery sama kolom tabel luar.

2. Pakai NOT IN di kolom yang bisa NULL

Udah dibahas panjang di atas. Kalau kolomnya nullable, pakai NOT EXISTS. Titik.

3. Naruh COUNT di dalam EXISTS

-- Boros, gak perlu
WHERE EXISTS (SELECT COUNT(*) FROM pesanan o WHERE ...)

COUNT(*) maksa database ngitung semua baris yang cocok. EXISTS cuma butuh satu. Pakai SELECT 1.

4. Kolom di klausa korelasi gak diindeks

EXISTS dijalanin sekali buat tiap baris tabel luar. Tanpa index di pesanan.pelanggan_id, tabel pesanan bakal di-scan penuh berkali-kali. Ini yang bikin orang salah nyalahin EXISTS sebagai fungsi yang lambat.

FAQ

Apa bedanya EXISTS dan IN di SQL?

EXISTS ngecek ada atau nggaknya baris, dan langsung berhenti begitu nemu satu yang cocok. IN ngumpulin dulu semua nilai dari subquery, baru dibandingin satu per satu. Di tabel kecil selisihnya gak kerasa. Di tabel jutaan baris, EXISTS biasanya jauh lebih ngebut. EXISTS juga aman dari NULL.

Kenapa NOT IN hasilnya kosong padahal datanya ada?

Hampir pasti gara-gara ada NULL di subquery-nya. Waktu SQL bandingin sebuah nilai dengan NULL, hasilnya bukan TRUE atau FALSE, tapi UNKNOWN. NOT IN butuh semua perbandingan bernilai TRUE, dan UNKNOWN bikin itu gak pernah kejadian. Solusinya pakai NOT EXISTS, atau tambahin WHERE kolom IS NOT NULL di dalam subquery.

Kenapa di dalam EXISTS orang nulis SELECT 1?

Karena isinya emang gak pernah dipakai. EXISTS cuma peduli apakah subquery-nya menghasilkan baris atau nggak, bukan apa isi barisnya. Kamu bisa nulis SELECT *, SELECT nama, atau bahkan SELECT 'apa aja' dan hasilnya sama persis. SELECT 1 udah jadi konvensi karena paling pendek.

Lebih cepat mana, EXISTS atau JOIN?

Tergantung tujuannya. Kalau kamu cuma mau ngecek keberadaan data dan gak butuh kolom dari tabel kedua, EXISTS lebih tepat dan gak bikin baris berlipat. Kalau kamu butuh kolom dari kedua tabel, JOIN yang bener. Optimizer PostgreSQL dan SQL Server modern sering ngubah keduanya jadi rencana eksekusi yang mirip.

Apakah EXISTS bisa dipakai tanpa korelasi ke tabel luar?

Bisa secara teknis, tapi hampir selalu salah. Kalau subquery-nya gak nyambung ke tabel luar, misalnya WHERE EXISTS (SELECT 1 FROM pesanan), hasilnya TRUE buat semua baris selama tabel pesanan gak kosong. Jadi filternya gak ngefek sama sekali. Selalu pastiin ada kondisi yang nyambungin kolom subquery dengan kolom tabel luar.

Penutup

Tiga hal yang perlu diinget:

  1. EXISTS berhenti di baris pertama yang cocok. Itu sumber kecepatannya.
  2. NOT IN ketemu NULL = hasil kosong, tanpa error. Pakai NOT EXISTS aja.
  3. Butuh kolom dari tabel kedua? Itu kerjaan JOIN, bukan EXISTS.

Semua query di atas siap copy-paste. Coba jalanin yang NOT IN dulu, liat hasilnya kosong, terus ganti jadi NOT EXISTS. Momen "oh iya ya" itu yang bikin nempel.

Latihan interaktifnya ada di halaman fungsi EXISTS. Konsep three-valued logic yang bikin NULL berbahaya aku jelasin di glosarium NULL.

Lanjut baca: Operator IN dan BETWEEN SQL — biar kamu tau kapan IN masih jadi pilihan yang paling tepat.

Coba Langsung

Mau praktek langsung? Mulai latihan SQL gratis

Latihan interaktif, langsung di browser.

Buka NgulikSQL →
Bagikan:
Bima
Ditulis oleh

Bima

Founder & Data Professional

Founder Ngulik Data. Passionate about making data analysis accessible for everyone.

Artikel Terkait

7 SQL Client Gratis Terbaik buat Analis Data (2026)
Tutorial SQL
10 Juli 2026•9 menit baca

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.

BimaBima
SQL Style Guide: Cara Nulis Query yang Enak Dibaca Tim
Tutorial SQL
7 Juli 2026•9 menit baca

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.

BimaBima
Take-Home Test SQL Data Analyst: Contoh Soal + Cara Ngerjainnya
Tutorial SQL
4 Juli 2026•11 menit baca

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.

BimaBima
Kembali ke Blog
Ngulik Data logoNgulik Data

Platform edukasi data lengkap untuk professionals Indonesia. Belajar SQL, Data Analysis, dan lebih banyak lagi dengan praktek langsung dan feedback real-time.

Copyright © 2026 - All rights reserved

LINKS
SupportPricingDatasetBlogAffiliates
LEGAL
Terms of servicesPrivacy policy
Ngulik Data
DatasetLeaderboardBlogStore