Cara Menggunakan Subquery di SQL (Dengan 10 Contoh Praktis)
Blog/Tutorial SQL/Cara Menggunakan Subquery di SQL (Dengan 10 Contoh Praktis)

Cara Menggunakan Subquery di SQL (Dengan 10 Contoh Praktis)

BimaBima
·21 Desember 2025·14 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

Terakhir diperbarui: 22 Desember 2025

TL;DR

Subquery itu query di dalam query. Bisa dipake di WHERE, FROM, atau SELECT. Pake buat filter, bikin tabel sementara, atau ngitung nilai buat perbandingan.

Apa Itu Subquery?

Pernah kepikiran ga, gimana caranya cari produk yang harganya di atas rata-rata? Atau gimana caranya nampilin customer yang belanja paling banyak?

Untuk kasus kayak gitu, kamu butuh yang namanya subquery. Subquery itu basically query di dalam query. Kamu nulis satu query, terus hasilnya dipake sama query luar.

Bayangin kayak gini: kamu mau beli baju yang harganya di bawah rata-rata. Pertama, kamu hitung dulu rata-rata harga semua baju. Baru setelah itu, kamu filter baju yang harganya di bawah angka itu. Nah, hitungan rata-rata itu ibarat subquery.

Kenapa Perlu Belajar Subquery?

Sebagai Data Analyst, kamu bakal sering nemuin case yang ga bisa diselesaiin cuma pake WHERE biasa. Contohnya:

  • Cari transaksi di atas rata-rata
  • Tampilin produk yang belum pernah kejual
  • Bandingkan performa tiap cabang dengan total keseluruhan
  • Filter data berdasarkan hasil agregasi tabel lain

Semua itu butuh subquery. Tanpa subquery, query kamu bakal jadi ribet banget atau bahkan ga mungkin dibikin.

Dataset yang Akan Kita Pakai

Buat tutorial ini, kita pakai dataset e-commerce lokal. Bayangin kamu jadi Data Analyst di startup marketplace Indonesia.

Tabel: produk

id nama_produk kategori harga stok
1 Batik Pekalongan Fashion 185000 50
2 Kopi Toraja 250g Makanan 75000 100
3 Tas Kulit Garut Fashion 450000 25
4 Sambal Bu Rudy Makanan 35000 200
5 Gelang Perak Bali Aksesoris 250000 30
6 Keripik Tempe Makanan 25000 150
7 Kaos Dagadu Fashion 95000 80
8 Dodol Betawi Makanan 45000 120
9 Cincin Perak Aksesoris 175000 40
10 Mukena Bali Fashion 320000 35

Tabel: transaksi

id tanggal customer_id produk_id qty total
1 2024-01-15 101 1 2 370000
2 2024-01-15 102 2 3 225000
3 2024-01-16 103 4 5 175000
4 2024-01-16 101 3 1 450000
5 2024-01-17 104 6 10 250000
6 2024-01-17 102 5 1 250000
7 2024-01-18 105 7 2 190000
8 2024-01-18 103 8 4 180000
9 2024-01-19 101 2 2 150000
10 2024-01-19 106 1 1 185000

Tabel: customer

id nama kota tgl_daftar
101 Budi Santoso Jakarta 2023-06-15
102 Siti Rahayu Bandung 2023-08-20
103 Andi Wijaya Surabaya 2023-09-10
104 Dewi Lestari Yogyakarta 2023-11-05
105 Reza Pratama Semarang 2024-01-02
106 Maya Putri Jakarta 2024-01-10

Jenis-Jenis Subquery

Ada 3 tempat utama di mana kamu bisa pake subquery:

  1. Subquery di WHERE - paling umum, buat filter data
  2. Subquery di FROM - bikin tabel sementara
  3. Subquery di SELECT - ngitung nilai buat tiap baris

Kita bahas satu-satu dengan contoh praktis ya.

Subquery di WHERE Clause

Ini jenis subquery yang paling sering dipake. Kamu pake hasil dari subquery buat filter data di query utama.

Contoh 1: Produk dengan Harga di Atas Rata-rata

Cari produk yang harganya di atas rata-rata semua produk.

SELECT nama_produk, kategori, harga
FROM produk
WHERE harga > (
    SELECT AVG(harga) FROM produk
);

Cara kerjanya:
1. Subquery SELECT AVG(harga) FROM produk dijalankan dulu, hasilnya 165500
2. Query utama filter produk yang harganya > 165500

Hasil:

nama_produk kategori harga
Batik Pekalongan Fashion 185000
Tas Kulit Garut Fashion 450000
Gelang Perak Bali Aksesoris 250000
Cincin Perak Aksesoris 175000
Mukena Bali Fashion 320000

Contoh 2: Customer dengan Total Belanja Tertinggi

Cari customer yang total belanjanya sama dengan nilai tertinggi.

SELECT c.nama, c.kota, SUM(t.total) AS total_belanja
FROM customer c
JOIN transaksi t ON c.id = t.customer_id
GROUP BY c.id, c.nama, c.kota
HAVING SUM(t.total) = (
    SELECT MAX(total_per_customer)
    FROM (
        SELECT customer_id, SUM(total) AS total_per_customer
        FROM transaksi
        GROUP BY customer_id
    ) AS sub
);

Hasil:

nama kota total_belanja
Budi Santoso Jakarta 970000

Di sini kita pake nested subquery. Subquery dalem ngitung total belanja per customer, subquery luar ambil nilai MAX-nya.

Contoh 3: Menggunakan IN dengan Subquery

Cari transaksi yang produknya termasuk kategori Fashion.

SELECT t.id, t.tanggal, p.nama_produk, t.total
FROM transaksi t
JOIN produk p ON t.produk_id = p.id
WHERE t.produk_id IN (
    SELECT id FROM produk WHERE kategori = 'Fashion'
);

Hasil:

id tanggal nama_produk total
1 2024-01-15 Batik Pekalongan 370000
4 2024-01-16 Tas Kulit Garut 450000
7 2024-01-18 Kaos Dagadu 190000
10 2024-01-19 Batik Pekalongan 185000

Contoh 4: Menggunakan NOT IN

Cari produk yang BELUM pernah terjual.

SELECT id, nama_produk, kategori
FROM produk
WHERE id NOT IN (
    SELECT DISTINCT produk_id FROM transaksi
);

Hasil:

id nama_produk kategori
9 Cincin Perak Aksesoris
10 Mukena Bali Fashion

Ini berguna banget buat analisis produk yang ga laku.

Contoh 5: Subquery dengan ANY/ALL

Cari produk yang harganya lebih mahal dari SEMUA produk kategori Makanan.

SELECT nama_produk, kategori, harga
FROM produk
WHERE harga > ALL (
    SELECT harga FROM produk WHERE kategori = 'Makanan'
);

Hasil:

nama_produk kategori harga
Batik Pekalongan Fashion 185000
Tas Kulit Garut Fashion 450000
Gelang Perak Bali Aksesoris 250000
Kaos Dagadu Fashion 95000
Cincin Perak Aksesoris 175000
Mukena Bali Fashion 320000

Harga tertinggi di kategori Makanan itu 75000 (Kopi Toraja). Jadi semua produk di atas 75000 masuk ke hasil.

Subquery di FROM Clause (Derived Table)

Subquery di FROM bikin tabel sementara yang bisa kamu query lagi. Ini powerful banget buat analisis yang kompleks.

Contoh 6: Ranking Customer berdasarkan Total Belanja

SELECT
    ranking.nama,
    ranking.kota,
    ranking.total_belanja,
    ranking.jumlah_transaksi
FROM (
    SELECT
        c.nama,
        c.kota,
        SUM(t.total) AS total_belanja,
        COUNT(*) AS jumlah_transaksi
    FROM customer c
    JOIN transaksi t ON c.id = t.customer_id
    GROUP BY c.id, c.nama, c.kota
) AS ranking
ORDER BY ranking.total_belanja DESC;

Hasil:

nama kota total_belanja jumlah_transaksi
Budi Santoso Jakarta 970000 3
Siti Rahayu Bandung 475000 2
Andi Wijaya Surabaya 355000 2
Dewi Lestari Yogyakarta 250000 1
Reza Pratama Semarang 190000 1
Maya Putri Jakarta 185000 1

Contoh 7: Perbandingan dengan Total Keseluruhan

Hitung persentase kontribusi tiap kategori terhadap total penjualan.

SELECT
    kategori_stats.kategori,
    kategori_stats.total_penjualan,
    total_stats.grand_total,
    ROUND(
        kategori_stats.total_penjualan * 100.0 / total_stats.grand_total,
        2
    ) AS persentase
FROM (
    SELECT
        p.kategori,
        SUM(t.total) AS total_penjualan
    FROM produk p
    JOIN transaksi t ON p.id = t.produk_id
    GROUP BY p.kategori
) AS kategori_stats
CROSS JOIN (
    SELECT SUM(total) AS grand_total FROM transaksi
) AS total_stats
ORDER BY persentase DESC;

Hasil:

kategori total_penjualan grand_total persentase
Fashion 1195000 2425000 49.28
Makanan 980000 2425000 40.41
Aksesoris 250000 2425000 10.31

Nah, ini insight yang valuable banget. Fashion nyumbang hampir 50% total penjualan!

Subquery di SELECT Clause (Scalar Subquery)

Subquery di SELECT dipake buat ngitung nilai yang bakal muncul sebagai kolom baru di tiap baris.

Contoh 8: Menampilkan Rata-rata di Setiap Baris

Tampilin harga produk beserta rata-rata harga kategorinya.

SELECT
    nama_produk,
    kategori,
    harga,
    (
        SELECT ROUND(AVG(harga), 0)
        FROM produk p2
        WHERE p2.kategori = p1.kategori
    ) AS avg_kategori,
    harga - (
        SELECT ROUND(AVG(harga), 0)
        FROM produk p2
        WHERE p2.kategori = p1.kategori
    ) AS selisih_dari_avg
FROM produk p1
ORDER BY kategori, harga DESC;

Hasil:

nama_produk kategori harga avg_kategori selisih_dari_avg
Gelang Perak Bali Aksesoris 250000 212500 37500
Cincin Perak Aksesoris 175000 212500 -37500
Tas Kulit Garut Fashion 450000 262500 187500
Mukena Bali Fashion 320000 262500 57500
Batik Pekalongan Fashion 185000 262500 -77500
Kaos Dagadu Fashion 95000 262500 -167500
Kopi Toraja 250g Makanan 75000 45000 30000
Dodol Betawi Makanan 45000 45000 0
Sambal Bu Rudy Makanan 35000 45000 -10000
Keripik Tempe Makanan 25000 45000 -20000

Ini berguna buat liat mana produk yang overpriced atau underpriced dibanding rata-rata kategorinya.

Contoh 9: Count Related Records

Tampilin produk beserta jumlah transaksinya.

SELECT
    p.nama_produk,
    p.kategori,
    p.harga,
    (
        SELECT COUNT(*)
        FROM transaksi t
        WHERE t.produk_id = p.id
    ) AS jumlah_terjual
FROM produk p
ORDER BY jumlah_terjual DESC;

Hasil:

nama_produk kategori harga jumlah_terjual
Batik Pekalongan Fashion 185000 2
Kopi Toraja 250g Makanan 75000 2
Tas Kulit Garut Fashion 450000 1
Sambal Bu Rudy Makanan 35000 1
Gelang Perak Bali Aksesoris 250000 1
Keripik Tempe Makanan 25000 1
Kaos Dagadu Fashion 95000 1
Dodol Betawi Makanan 45000 1
Cincin Perak Aksesoris 175000 0
Mukena Bali Fashion 320000 0

Correlated Subquery

Correlated subquery itu subquery yang reference kolom dari query luar. Setiap baris di query utama, subquery-nya dijalankan ulang.

Contoh 10: Cari Transaksi Tertinggi per Customer

SELECT
    t.id,
    c.nama,
    t.tanggal,
    t.total
FROM transaksi t
JOIN customer c ON t.customer_id = c.id
WHERE t.total = (
    SELECT MAX(total)
    FROM transaksi t2
    WHERE t2.customer_id = t.customer_id
);

Hasil:

id nama tanggal total
4 Budi Santoso 2024-01-16 450000
6 Siti Rahayu 2024-01-17 250000
5 Dewi Lestari 2024-01-17 250000
7 Reza Pratama 2024-01-18 190000
10 Maya Putri 2024-01-19 185000
8 Andi Wijaya 2024-01-18 180000

Di sini, t.customer_id di subquery nge-refer ke baris yang lagi diproses di query utama.

EXISTS vs IN: Kapan Pake Yang Mana?

Kadang kamu bisa pake IN atau EXISTS buat hasil yang sama. Tapi ada perbedaan performa.

Pake IN

SELECT nama_produk
FROM produk
WHERE id IN (SELECT produk_id FROM transaksi);

Pake EXISTS

SELECT nama_produk
FROM produk p
WHERE EXISTS (
    SELECT 1 FROM transaksi t WHERE t.produk_id = p.id
);

Kapan pake apa?
- EXISTS lebih cepat kalau subquery hasilnya banyak
- IN lebih cepat kalau subquery hasilnya sedikit
- EXISTS lebih aman untuk handle NULL
- IN lebih readable untuk case simple

Common Mistakes yang Harus Dihindari

Mistake 1: Subquery Return Multiple Rows Padahal Expect Single Value

-- SALAH kalau subquery return > 1 row
SELECT * FROM produk
WHERE harga = (SELECT harga FROM produk WHERE kategori = 'Fashion');

Fix: Pake IN atau agregasi function.

-- BENAR
SELECT * FROM produk
WHERE harga IN (SELECT harga FROM produk WHERE kategori = 'Fashion');

Mistake 2: Subquery Terlalu Kompleks

Kadang subquery bisa di-replace dengan JOIN yang lebih efficient.

-- Bisa jadi lambat
SELECT nama_produk
FROM produk
WHERE id IN (
    SELECT produk_id FROM transaksi WHERE total > 200000
);

-- Lebih efficient pake JOIN
SELECT DISTINCT p.nama_produk
FROM produk p
JOIN transaksi t ON p.id = t.produk_id
WHERE t.total > 200000;

Mistake 3: Lupa Alias di Derived Table

-- SALAH
SELECT * FROM (
    SELECT kategori, SUM(total) FROM transaksi GROUP BY kategori
);

-- BENAR
SELECT * FROM (
    SELECT kategori, SUM(total) AS total
    FROM transaksi
    GROUP BY kategori
) AS sub;  -- Wajib pake alias

Subquery vs CTE (Common Table Expression)

Buat query yang kompleks, kadang lebih baik pake CTE daripada nested subquery.

-- Pake Subquery (susah dibaca)
SELECT *
FROM (
    SELECT kategori, SUM(total) AS total
    FROM (
        SELECT p.kategori, t.total
        FROM produk p
        JOIN transaksi t ON p.id = t.produk_id
    ) AS sub1
    GROUP BY kategori
) AS sub2
WHERE total > 300000;

-- Pake CTE (lebih readable)
WITH sales_data AS (
    SELECT p.kategori, t.total
    FROM produk p
    JOIN transaksi t ON p.id = t.produk_id
),
kategori_total AS (
    SELECT kategori, SUM(total) AS total
    FROM sales_data
    GROUP BY kategori
)
SELECT * FROM kategori_total WHERE total > 300000;

CTE bikin query lebih modular dan gampang di-debug.

Tips Praktis

1. Test Subquery-nya Dulu

Sebelum jalanin query lengkap, test subquery-nya terpisah. Pastiin hasilnya sesuai ekspektasi.

2. Perhatikan Performa

Subquery di SELECT atau correlated subquery bisa lambat karena dijalankan per baris. Kalau datanya banyak, consider pake JOIN atau CTE.

3. Pake Alias yang Jelas

Kasih alias yang meaningful biar query gampang dibaca.

4. Comment Query Kompleks

Kalau subquery-nya nested, tambahin comment biar teammate (atau kamu di masa depan) bisa ngerti.

Kesimpulan

Subquery itu tool yang powerful buat Data Analyst. Inget poin-poin utama:

  1. Subquery di WHERE - buat filter berdasarkan hasil query lain
  2. Subquery di FROM - bikin tabel sementara (derived table)
  3. Subquery di SELECT - ngitung nilai per baris
  4. Correlated subquery - subquery yang reference query luar
  5. EXISTS vs IN - pilih yang sesuai dengan use case

Mulai dari contoh simple, terus gradually naikin kompleksitasnya. Latihan bikin subquery sendiri pake dataset yang kamu punya.

Happy querying! Cek nguliksql.id buat latihan lebih banyak!

Bagikan:
Bima
Ditulis oleh

Bima

Founder & Data Professional

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

Artikel Terkait

Fungsi GROUP BY dan HAVING di SQL: Panduan Lengkap
Tutorial SQL
22 Desember 2025•12 menit baca

Fungsi GROUP BY dan HAVING di SQL: Panduan Lengkap

Pelajari cara pakai GROUP BY dan HAVING untuk agregasi data di SQL dengan contoh dataset penjualan UMKM Indonesia

BimaBima
Perbedaan INNER JOIN, LEFT JOIN, RIGHT JOIN, dan FULL JOIN di SQL
Tutorial SQL
19 Desember 2025•12 menit baca

Perbedaan INNER JOIN, LEFT JOIN, RIGHT JOIN, dan FULL JOIN di SQL

Belajar perbedaan jenis-jenis JOIN di SQL dengan contoh praktis dan visualisasi. Panduan lengkap INNER, LEFT, RIGHT, dan FULL JOIN untuk pemula.

BimaBima
Cara Install PostgreSQL di Windows, Mac, dan Linux (Panduan Lengkap)
Tutorial SQL
19 Desember 2025•12 menit baca

Cara Install PostgreSQL di Windows, Mac, dan Linux (Panduan Lengkap)

Panduan step-by-step install PostgreSQL di Windows, macOS, dan Linux lengkap dengan pgAdmin dan troubleshooting

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
SupportPricingBlogAffiliates
LEGAL
Terms of servicesPrivacy policy