java php laravel linux mysql sql bootstrap html css query java php laravel linux mysql sql bootstrap html css query

Wednesday, April 8, 2026

query union all mysql

Beranda Tutorial MySQL Artikel 24

๐Ÿ”ด Level Lanjutan ๐Ÿ”— UNION & UNION ALL ⏱️ ~9 Menit Baca ๐Ÿ“˜ Artikel 24 / 28

Menggabungkan Hasil Query: UNION dan UNION ALL

2
Perintah SQL
7
Contoh Query
9
Menit Baca
3
Tabel Data

Bayangkan kamu punya dua laporan penjualan — satu dari toko fisik, satu dari toko online — dan bosmu minta satu laporan gabungan dalam satu tabel bersih. Kamu nggak mau repot copas manual, kan? Di MySQL, kebutuhan "gabungkan dua hasil query jadi satu" ini diselesaikan dengan sangat elegan oleh UNION MySQL. Cukup dua kata, dua query pun berpadu jadi satu.

Selamat datang di Artikel ke-24 dari 28 dalam seri Belajar Query SQL MySQL! Kita sudah jauh banget — dari SELECT dasar, JOIN, hingga subquery di artikel sebelumnya (Artikel 23). Sekarang giliran UNION MySQL dan UNION ALL — dua operator yang membiarkan kamu menumpuk hasil dari beberapa query sekaligus.

Di artikel ini kamu akan belajar perbedaan UNION vs UNION ALL, aturan wajib yang harus dipatuhi, cara menyortir hasil gabungan, dan kapan masing-masing operator ini paling tepat dipakai — semuanya dengan studi kasus toko online yang langsung bisa kamu coba.

๐Ÿ’ก Fakta Menarik

UNION sudah ada dalam standar SQL sejak SQL-86 — artinya operator ini sudah eksis lebih dari 35 tahun! Meski terlihat sederhana, UNION adalah fondasi dari banyak laporan bisnis kompleks. Sistem reporting besar seperti Google Analytics dan Tableau secara internal menggunakan prinsip UNION untuk menggabungkan data dari berbagai sumber.

1. Apa Itu UNION MySQL? Konsep & Aturan Wajib

Kalau JOIN menggabungkan data secara horizontal (menambah kolom), maka UNION MySQL menggabungkan data secara vertikal (menumpuk baris). Analoginya: JOIN itu seperti menggabungkan dua lembar kertas secara sejajar, sedangkan UNION itu seperti menumpuk dua tumpukan kertas jadi satu.

๐Ÿ“‹ Sintaks UNION dan UNION ALL
-- Sintaks dasar UNION (menghapus duplikat)
SELECT kolom1, kolom2, ...   -- Query pertama
FROM tabel_a
UNION
SELECT kolom1, kolom2, ...   -- Query kedua (jumlah kolom harus sama!)
FROM tabel_b;

-- Sintaks UNION ALL (TIDAK menghapus duplikat, lebih cepat)
SELECT kolom1, kolom2, ...
FROM tabel_a
UNION ALL
SELECT kolom1, kolom2, ...
FROM tabel_b;

-- Aturan wajib:
-- 1. Jumlah kolom di setiap SELECT harus sama
-- 2. Tipe data tiap kolom harus kompatibel
-- 3. Nama kolom hasil diambil dari SELECT pertama
-- 4. ORDER BY hanya boleh di akhir query terakhir

๐Ÿ” Contoh Dasar: Gabungkan daftar nama pelanggan dan nama supplier

-- Gabungkan nama dari dua tabel berbeda
SELECT nama, 'Pelanggan' AS tipe
FROM pelanggan
UNION
SELECT nama_supplier, 'Supplier' AS tipe
FROM supplier
ORDER BY nama;
nama tipe
Andi Saputra Pelanggan
Budi Santoso Pelanggan
CV Maju Jaya Supplier
PT Elektronik Nusantara Supplier
Rina Dewi Pelanggan

* Hasil diurutkan berdasarkan nama, digabung dari dua tabel berbeda dalam satu output.

✅ Tip Praktis

Tambahkan kolom literal seperti 'Pelanggan' AS tipe untuk memberi label asal data setiap baris — sangat berguna saat hasil UNION digabung dari tabel-tabel dengan struktur berbeda agar tetap bisa dibedakan.

2. UNION vs UNION ALL — Kapan Pakai Mana?

Ini adalah pertanyaan nomor satu yang selalu muncul: "UNION biasa atau UNION ALL?" Perbedaannya satu hal tapi dampaknya besar: UNION secara otomatis menghapus baris duplikat dari hasil gabungan (mirip seperti SELECT DISTINCT), sedangkan UNION ALL menjaga semua baris termasuk yang duplikat.

Analoginya: UNION itu seperti gabungin dua daftar tamu undangan dan coret nama yang dobel. UNION ALL itu gabungin semua apa adanya — nama dobel tetap dua kali muncul. Konsekuensinya: UNION lebih lambat karena MySQL harus melakukan pengecekan duplikat, sementara UNION ALL lebih cepat karena langsung tumpuk saja.

๐Ÿ” Contoh: Produk dari dua gudang — lihat perbedaan UNION vs UNION ALL

-- Data dari dua gudang, beberapa produk ada di keduanya

-- Dengan UNION: duplikat dihapus
SELECT id_produk, nama_produk FROM gudang_jakarta
UNION
SELECT id_produk, nama_produk FROM gudang_surabaya;

-- Dengan UNION ALL: duplikat TETAP ada
SELECT id_produk, nama_produk FROM gudang_jakarta
UNION ALL
SELECT id_produk, nama_produk FROM gudang_surabaya;

Hasil UNION (5 baris)

id_produk nama_produk
P001Laptop ProMax
P002Smartphone UltraX
P003Headphone BassMax
P004Charger Turbo
P005Kamera Mirrorless

Hasil UNION ALL (7 baris)

id_produk nama_produk
P001Laptop ProMax
P002Smartphone UltraX
P003Headphone BassMax
P001Laptop ProMax ⚠️
P004Charger Turbo
P002Smartphone UltraX ⚠️
P005Kamera Mirrorless

⚠️ Baris merah = duplikat dari gudang ke-2

⚠️ Perhatikan Performa

UNION (tanpa ALL) melakukan operasi sorting dan deduplication yang cukup berat. Jika kamu yakin data tidak ada duplikat — atau memang butuh semua duplikat — selalu pakai UNION ALL. Di tabel berjuta baris, perbedaan kecepatannya bisa signifikan.

3. UNION MySQL untuk Laporan Gabungan — Studi Kasus Toko Online

Mari kita lihat penggunaan nyata UNION di konteks toko online. Misalnya kamu perlu membuat laporan aktivitas gabungan: tampilkan semua transaksi (pesanan yang selesai dan yang dibatalkan) dalam satu tabel laporan dengan kolom status yang jelas.

๐Ÿ” Contoh: Laporan gabungan pesanan selesai + pesanan dibatalkan

-- Laporan: semua pesanan selesai dan dibatalkan dalam satu view
SELECT
    id_pesanan,
    nama AS nama_pelanggan,
    total_harga,
    tanggal,
    'Selesai' AS status_pesanan
FROM pesanan_selesai ps
JOIN pelanggan p ON ps.id_pelanggan = p.id_pelanggan

UNION ALL

SELECT
    id_pesanan,
    nama AS nama_pelanggan,
    total_harga,
    tanggal,
    'Dibatalkan' AS status_pesanan
FROM pesanan_batal pb
JOIN pelanggan p ON pb.id_pelanggan = p.id_pelanggan

ORDER BY tanggal DESC;   -- ORDER BY hanya di bagian paling akhir!
id_pesanan nama_pelanggan total_harga tanggal status_pesanan
ORD-0091 Budi Santoso Rp 8.750.000 2024-03-15 Selesai
ORD-0088 Rina Dewi Rp 450.000 2024-03-14 Dibatalkan
ORD-0085 Andi Saputra Rp 12.500.000 2024-03-12 Selesai
ORD-0081 Siti Rahayu Rp 175.000 2024-03-10 Dibatalkan
✅ Tip Praktis — ORDER BY di UNION

Klausa ORDER BY hanya boleh ditulis satu kali di bagian paling akhir setelah semua blok SELECT. MySQL akan mengurutkan seluruh hasil gabungan. Jika kamu mau mengurutkan per blok saja, bungkus tiap blok dalam subquery dengan alias terlebih dahulu.

4. UNION dengan Lebih dari Dua Query & Menggunakan LIMIT

UNION tidak terbatas dua query saja — kamu bisa menumpuk tiga, empat, bahkan lebih banyak query sekaligus. Selama aturan jumlah kolom dan tipe data terpenuhi, MySQL akan memprosesnya satu per satu dari atas ke bawah.

๐Ÿ” Contoh: Top 3 produk terlaris dari tiga kategori berbeda

-- Ambil 1 produk terlaris dari masing-masing 3 kategori
(
  SELECT nama_produk, kategori, SUM(qty) AS total_terjual
  FROM pesanan JOIN produk USING(id_produk)
  WHERE kategori = 'Elektronik'
  GROUP BY id_produk ORDER BY total_terjual DESC LIMIT 1
)
UNION ALL
(
  SELECT nama_produk, kategori, SUM(qty) AS total_terjual
  FROM pesanan JOIN produk USING(id_produk)
  WHERE kategori = 'Fashion'
  GROUP BY id_produk ORDER BY total_terjual DESC LIMIT 1
)
UNION ALL
(
  SELECT nama_produk, kategori, SUM(qty) AS total_terjual
  FROM pesanan JOIN produk USING(id_produk)
  WHERE kategori = 'Aksesoris'
  GROUP BY id_produk ORDER BY total_terjual DESC LIMIT 1
);
-- Catatan: setiap blok dikurung agar ORDER BY + LIMIT per blok valid
nama_produk kategori total_terjual
Smartphone UltraX Elektronik 247
Kaos Polos Premium Fashion 189
Charger Turbo 65W Aksesoris 134
⚠️ Trik LIMIT per Blok

Untuk menggunakan ORDER BY dan LIMIT per blok SELECT (bukan untuk keseluruhan hasil), bungkus setiap blok dalam tanda kurung ( ). Tanpa kurung, MySQL akan menganggap ORDER BY berlaku untuk semua hasil gabungan.

๐Ÿงช Panduan Praktikum: UNION dari Nol

1

Buat Dua Tabel Sederhana untuk Latihan

CREATE TABLE pelanggan_lama (
  id INT PRIMARY KEY, nama VARCHAR(100), kota VARCHAR(50)
);
CREATE TABLE pelanggan_baru (
  id INT PRIMARY KEY, nama VARCHAR(100), kota VARCHAR(50)
);
INSERT INTO pelanggan_lama VALUES
  (1,'Andi','Jakarta'), (2,'Budi','Bandung'), (3,'Citra','Surabaya');
INSERT INTO pelanggan_baru VALUES
  (3,'Citra','Surabaya'), (4,'Dewi','Medan'), (5,'Eko','Yogyakarta');
2

Coba UNION — Lihat Duplikat Dihapus

-- Hasilnya 5 baris (Citra hanya muncul sekali)
SELECT nama, kota FROM pelanggan_lama
UNION
SELECT nama, kota FROM pelanggan_baru;
3

Coba UNION ALL — Lihat Perbedaannya

-- Hasilnya 6 baris (Citra muncul dua kali!)
SELECT nama, kota FROM pelanggan_lama
UNION ALL
SELECT nama, kota FROM pelanggan_baru;
4

Tantangan: Tambahkan Kolom Label & Urutkan

SELECT nama, kota, 'Lama' AS segmen
FROM pelanggan_lama
UNION
SELECT nama, kota, 'Baru' AS segmen
FROM pelanggan_baru
ORDER BY kota ASC, nama ASC;

๐Ÿ“Š Ringkasan: UNION vs UNION ALL vs JOIN

Tabel ini merangkum kapan kamu harus memilih operator mana:

Aspek UNION UNION ALL JOIN
Arah penggabungan Vertikal (tumpuk baris) Vertikal (tumpuk baris) Horizontal (tambah kolom)
Duplikat ✅ Dihapus otomatis ⚠️ Tetap ada Tergantung kondisi ON
Performa ⚠️ Lebih lambat (dedup) ✅ Lebih cepat ✅ Cepat dengan index
Syarat kolom Jumlah & tipe harus sama Jumlah & tipe harus sama Butuh kolom relasi (key)
Use case ideal Gabung + bersihkan duplikat Laporan log/audit lengkap Relasi antar tabel (FK)
ORDER BY Hanya di akhir query Hanya di akhir query Di mana saja
๐Ÿ’ก Insight dari Lapangan #1 — UNION sebagai "Fake View"

Di proyek nyata, UNION sering dipakai untuk membuat virtual unified table dari beberapa tabel terpisah (misalnya tabel log per bulan atau tabel arsip per tahun). Daripada membuat VIEW resmi, developer kadang langsung embed UNION sebagai subquery di dalam FROM untuk laporan ad-hoc yang cepat.

๐Ÿ’ก Insight dari Lapangan #2 — Nama Kolom Ikut Query Pertama

Nama kolom di hasil UNION selalu diambil dari SELECT pertama. Jadi kalau query pertama punya kolom bernama tgl_pesan dan query kedua punya tgl_batal, hasilnya akan bernama tgl_pesan. Gunakan alias (AS nama_kolom) di query pertama untuk memberi nama yang tepat:

SELECT tgl_pesan AS tanggal_aktivitas, 'Pesan' AS jenis FROM pesanan
UNION ALL
SELECT tgl_batal -- kolom ini otomatis ikut nama "tanggal_aktivitas", 'Batal' FROM pembatalan;

๐ŸŽฏ Kesimpulan

  • UNION MySQL menggabungkan hasil dua query atau lebih secara vertikal (menumpuk baris).
  • UNION menghapus duplikat secara otomatis; UNION ALL mempertahankan semua baris termasuk duplikat.
  • Aturan wajib: jumlah kolom dan tipe data di setiap SELECT harus kompatibel.
  • Nama kolom hasil selalu mengikuti SELECT pertama — gunakan alias untuk kontrol penuh.
  • ORDER BY hanya boleh satu kali di bagian paling akhir — kecuali per blok dibungkus dalam tanda kurung.
  • Gunakan UNION ALL secara default untuk performa; ganti ke UNION hanya jika benar-benar perlu menghapus duplikat.

UNION dan UNION ALL adalah alat yang ringan tapi sering underestimated. Begitu kamu mulai bikin laporan dari banyak sumber data, kamu akan mengerti kenapa operator ini ada di setiap toolkit developer SQL yang serius. Empat artikel lagi menuju finish line seri ini — tetap semangat! ๐Ÿ

Artikel Berikutnya dalam Seri

Artikel 25: VIEW di MySQL — Membuat Tabel Virtual yang Bisa Dipakai Ulang

Sudah capek nulis query panjang yang sama berulang kali? VIEW adalah jawabannya! Pelajari cara membuat tabel virtual yang menyimpan query kompleks dan bisa dipanggil seperti tabel biasa kapanpun kamu butuhkan.

Baca Artikel 25 →
#MySQL #SQL #Database #Query #Tutorial #UNION MySQL #UNION ALL #BelajarSQL

subquery mysql nested select

Beranda Tutorial MySQL Artikel 23

๐Ÿ”ด Level Lanjutan ๐Ÿ—ƒ️ Subquery & Nested SELECT ⏱️ ~10 Menit Baca ๐Ÿ“˜ Artikel 23 / 28

Query di Dalam Query: Subquery dan Nested SELECT

6
Jenis Subquery
8
Contoh Query
10
Menit Baca
3
Tabel Data

Pernah gak kamu lagi belanja online, terus kepikiran: "Produk apa sih yang paling laris dari semua kategori yang tersedia?" — Untuk menjawab pertanyaan kayak gitu, kamu butuh dua langkah: pertama cari daftar kategori, baru cari produk terlaris di tiap kategori. Di dunia MySQL, proses dua-langkah inilah yang diselesaikan oleh subquery MySQL nested SELECT — sebuah query yang berjalan di dalam query lain.

Selamat datang di Artikel ke-23 dari 28 dalam seri Belajar Query SQL MySQL! Di artikel ini, kita bakal kupas tuntas teknik subquery MySQL nested SELECT — mulai dari konsep dasarnya, cara kerjanya di klausa WHERE, FROM, dan SELECT, hingga perbandingannya dengan JOIN. Kalau kamu sudah melewati JOIN di artikel-artikel sebelumnya, subquery ini akan terasa seperti senjata baru yang bikin SQL-mu jauh lebih ekspresif.

Semua contoh menggunakan studi kasus toko online dengan tabel produk, pelanggan, dan pesanan — biar langsung relate dan bisa kamu praktikkan.

๐Ÿ’ก Fakta Menarik

Menurut survei Stack Overflow Developer Survey, subquery adalah salah satu fitur SQL yang paling sering "takut dipakai" oleh developer junior — padahal lebih dari 70% query analitik di aplikasi e-commerce nyata menggunakan subquery dalam satu bentuk atau lainnya. Setelah artikel ini, kamu nggak akan takut lagi!

1. Apa Itu Subquery? Analogi & Konsep Dasar

Bayangkan kamu minta tolong teman: "Beliin aku minum yang sama kayak yang dibeli si Budi kemarin." Sebelum bisa beliin, temanmu harus tanya dulu ke Budi beli apa — itu adalah query dalam query. Di MySQL, konsepnya persis sama: subquery adalah SELECT yang dieksekusi lebih dulu, hasilnya dipakai oleh query luar (outer query).

Subquery selalu ditulis di dalam tanda kurung ( ) dan bisa muncul di klausa WHERE, FROM, maupun SELECT.

๐Ÿ“‹ Sintaks Dasar Subquery
-- Struktur umum subquery di WHERE
SELECT kolom1, kolom2
FROM tabel_luar
WHERE kolom_x operator (
    -- Ini adalah subquery (inner query)
    SELECT kolom_y
    FROM tabel_dalam
    WHERE kondisi_tertentu
);

-- Operator bisa berupa: =, >, <, IN, NOT IN, EXISTS, ANY, ALL

๐Ÿ” Contoh: Tampilkan produk dengan harga di atas rata-rata

-- Tampilkan produk yang harganya di atas rata-rata semua produk
SELECT nama_produk, harga, kategori
FROM produk
WHERE harga > (
    SELECT AVG(harga)   -- subquery: hitung rata-rata harga
    FROM produk
);
nama_produk harga kategori
Laptop ProMax 15 Rp 12.500.000 Elektronik
Smartphone UltraX Rp 8.750.000 Elektronik
Kamera Mirrorless Z Rp 9.200.000 Elektronik

* AVG(harga) = Rp 5.300.000 — hanya produk di atas nilai ini yang muncul.

✅ Tip Praktis

Subquery di klausa WHERE yang mengembalikan satu nilai (scalar subquery) paling aman untuk pemula. Pastikan inner query tidak mengembalikan lebih dari satu baris jika kamu menggunakan operator =.

2. Subquery dengan IN dan NOT IN — Filter Berdasarkan Daftar Dinamis

Kalau = hanya cocok untuk subquery yang mengembalikan satu nilai, operator IN adalah sahabatmu ketika subquery menghasilkan banyak baris. Analoginya: kamu punya daftar nama teman yang sudah RSVP ke acaramu, lalu kamu mau cari data lengkap mereka di buku kontak — itulah IN.

๐Ÿ” Contoh: Tampilkan pelanggan yang pernah memesan produk kategori "Elektronik"

-- Cari ID produk Elektronik dulu, lalu cari pelanggan yang memesannya
SELECT nama, email
FROM pelanggan
WHERE id_pelanggan IN (
    SELECT DISTINCT id_pelanggan   -- subquery: ambil ID pelanggan
    FROM pesanan
    WHERE id_produk IN (
        SELECT id_produk           -- nested subquery: ID produk Elektronik
        FROM produk
        WHERE kategori = 'Elektronik'
    )
);
nama email
Andi Saputra andi@example.com
Rina Dewi rina@example.com
Budi Santoso budi@example.com

๐Ÿ” Contoh NOT IN: Pelanggan yang BELUM pernah pesan sama sekali

-- Pelanggan yang tidak ada di tabel pesanan sama sekali
SELECT nama, email
FROM pelanggan
WHERE id_pelanggan NOT IN (
    SELECT DISTINCT id_pelanggan
    FROM pesanan
    WHERE id_pelanggan IS NOT NULL  -- PENTING: handle NULL!
);
⚠️ Peringatan Penting

Saat menggunakan NOT IN, kalau subquery-nya mengembalikan satu saja nilai NULL, keseluruhan query akan mengembalikan result kosong! Selalu tambahkan WHERE kolom IS NOT NULL di dalam subquery-mu.

3. Subquery di Klausa FROM — Derived Table (Tabel Sementara)

Nah, ini yang agak bikin pusing tapi super powerful. Subquery bisa dipakai sebagai sumber data di klausa FROM — seolah-olah subquery itu adalah tabel sungguhan. Ini disebut derived table. Analoginya: kamu bikin catatan coretan dulu di kertas baru, lalu kertas itu kamu jadikan sumber data untuk laporan resmi.

Derived table wajib diberi alias — MySQL tidak akan mengizinkan tanpanya.

๐Ÿ” Contoh: Tampilkan pelanggan dengan total belanja di atas rata-rata

-- Langkah 1 (inner): Hitung total belanja per pelanggan
-- Langkah 2 (outer): Filter yang di atas rata-rata
SELECT p.nama, ringkasan.total_belanja
FROM pelanggan p
JOIN (
    SELECT id_pelanggan,
           SUM(total_harga) AS total_belanja   -- subquery sebagai tabel
    FROM pesanan
    GROUP BY id_pelanggan
) AS ringkasan                                 -- alias WAJIB ada!
  ON p.id_pelanggan = ringkasan.id_pelanggan
WHERE ringkasan.total_belanja > (
    SELECT AVG(total_harga) FROM pesanan
)
ORDER BY ringkasan.total_belanja DESC;
nama total_belanja
Rina Dewi Rp 23.450.000
Budi Santoso Rp 18.200.000
Andi Saputra Rp 15.900.000
✅ Insight dari Lapangan

Derived table di klausa FROM adalah alternatif elegan dari CTE (WITH ... AS). Untuk query yang pendek, derived table lebih ringkas. Untuk query yang panjang dan perlu dibaca ulang, gunakan CTE agar lebih mudah di-debug.

4. Subquery di Klausa SELECT — Kolom yang Dihitung Dinamis

Selain WHERE dan FROM, subquery juga bisa masuk langsung ke daftar kolom di SELECT. Hasilnya berupa kolom kalkulasi yang dihitung per baris. Ini disebut correlated subquery karena inner query mengacu pada nilai dari outer query (berjalan per baris).

๐Ÿ” Contoh: Tampilkan setiap produk beserta jumlah kali dipesan

-- Correlated subquery: inner query mengacu ke p.id_produk (outer)
SELECT
    nama_produk,
    harga,
    (
        SELECT COUNT(*)
        FROM pesanan ps
        WHERE ps.id_produk = p.id_produk   -- korelasi ke outer query
    ) AS jumlah_pesanan
FROM produk p
ORDER BY jumlah_pesanan DESC;
nama_produk harga jumlah_pesanan
Smartphone UltraX Rp 8.750.000 47
Headphone BassMax Rp 450.000 38
Laptop ProMax 15 Rp 12.500.000 22
Charger Turbo 65W Rp 175.000 15
⚠️ Perhatikan Performa

Correlated subquery di klausa SELECT dieksekusi satu kali per baris dari outer query. Jika tabel produk punya 10.000 baris, subquery dijalankan 10.000 kali! Untuk dataset besar, lebih efisien menggunakan LEFT JOIN + GROUP BY atau derived table.

๐Ÿงช Panduan Praktikum: Subquery dari Nol

1

Siapkan Tabel & Data Contoh

CREATE TABLE produk (
  id_produk INT PRIMARY KEY AUTO_INCREMENT,
  nama_produk VARCHAR(100),
  harga DECIMAL(15,2),
  kategori VARCHAR(50)
);

CREATE TABLE pelanggan (
  id_pelanggan INT PRIMARY KEY AUTO_INCREMENT,
  nama VARCHAR(100),
  email VARCHAR(100)
);

CREATE TABLE pesanan (
  id_pesanan INT PRIMARY KEY AUTO_INCREMENT,
  id_pelanggan INT,
  id_produk INT,
  total_harga DECIMAL(15,2),
  tanggal DATE
);
2

Mulai dengan Subquery Sederhana (Scalar)

Coba cari produk termahal menggunakan subquery:

SELECT nama_produk, harga
FROM produk
WHERE harga = (SELECT MAX(harga) FROM produk);
3

Coba Subquery dengan IN

Tampilkan produk yang pernah ada dalam pesanan:

SELECT nama_produk, harga
FROM produk
WHERE id_produk IN (
    SELECT DISTINCT id_produk
    FROM pesanan
    WHERE id_produk IS NOT NULL
);
4

Tantangan: Buat Nested Subquery 2 Level

Cari nama pelanggan yang memesan produk kategori "Elektronik" dengan harga di atas 5 juta:

SELECT nama FROM pelanggan
WHERE id_pelanggan IN (
    SELECT DISTINCT id_pelanggan FROM pesanan
    WHERE id_produk IN (
        SELECT id_produk FROM produk
        WHERE kategori = 'Elektronik'
          AND harga > 5000000
    )
);

๐Ÿ“Š Perbandingan: Subquery vs JOIN

Pertanyaan klasik: kapan pakai subquery, kapan pakai JOIN? Ini perbandingan singkatnya:

Aspek Subquery JOIN
Keterbacaan ✅ Lebih mudah dibaca untuk logika bertingkat ⚡ Lebih ringkas untuk relasi sederhana
Performa ⚠️ Correlated subquery bisa lambat di data besar ✅ Umumnya lebih cepat dengan index yang tepat
Fleksibilitas ✅ Bisa di WHERE, FROM, SELECT sekaligus ⚡ Hanya di FROM/ON clause
Agregasi bertingkat ✅ Ideal untuk "max dari max" atau "avg dari sum" ⚠️ Butuh derived table atau CTE
Duplikasi baris ✅ Tidak menghasilkan duplikat ⚠️ Bisa menghasilkan duplikat jika tidak pakai DISTINCT
Kapan digunakan? Filter dinamis, agregasi bertingkat, derived table Gabung data dari dua tabel atau lebih secara langsung
๐Ÿ’ก Tips Praktis #1 — Debug Subquery Seperti Pro

Saat subquery-mu tidak menghasilkan output yang diharapkan, jalankan inner query terlebih dahulu secara terpisah. Copy bagian dalam kurung, eksekusi sendiri, dan periksa hasilnya. Ini cara tercepat untuk isolasi bug tanpa perlu menebak-nebak.

๐Ÿ’ก Tips Praktis #2 — Gunakan EXISTS untuk Performa Lebih Baik

Ketika kamu hanya perlu mengecek apakah ada data yang cocok (bukan mengambil nilainya), gunakan EXISTS — ini lebih efisien dari IN pada data besar karena MySQL berhenti mencari begitu satu baris ditemukan.

-- EXISTS: lebih cepat untuk "apakah ada pesanan?"
SELECT nama FROM pelanggan p
WHERE EXISTS (
    SELECT 1 FROM pesanan ps
    WHERE ps.id_pelanggan = p.id_pelanggan
);

๐ŸŽฏ Kesimpulan

  • Subquery MySQL nested SELECT adalah query yang berjalan di dalam query lain, dieksekusi terlebih dahulu.
  • Bisa dipakai di klausa WHERE (filter), FROM (derived table), dan SELECT (kolom kalkulasi).
  • Operator IN/NOT IN cocok untuk subquery multi-baris; = untuk scalar.
  • Selalu hati-hati dengan NULL di NOT IN — tambahkan filter IS NOT NULL.
  • Untuk performa optimal di data besar, pertimbangkan EXISTS, JOIN, atau CTE.
  • Debug dengan cara menjalankan inner query secara terpisah terlebih dahulu.

Subquery ibarat superkekuatan di gudang senjata SQL-mu — memang butuh sedikit waktu untuk terbiasa, tapi begitu kamu menguasainya, query yang dulu terasa mustahil jadi terasa natural. Seri kita hampir selesai — 5 artikel lagi menuju finish line! ๐Ÿš€

Artikel Berikutnya dalam Seri

Artikel 24: Common Table Expressions (CTE) dengan WITH

Subquery sudah kamu kuasai — sekarang saatnya naik level ke CTE! Pelajari cara menulis query kompleks yang jauh lebih mudah dibaca dan di-debug menggunakan klausa WITH di MySQL 8+.

Baca Artikel 24 →
#MySQL #SQL #Database #Query #Tutorial #subquery MySQL nested SELECT #BelajarSQL #NestedSELECT

join multi table mysql

Beranda Tutorial MySQL Artikel 22
๐Ÿ”ด Lanjutan ๐Ÿ”— Multi-Table JOIN ⏱ 13 menit baca ๐Ÿ“˜ Artikel 22/28

JOIN Lebih dari Dua Tabel Sekaligus:
Multi-Table JOIN MySQL

Satu JOIN sudah bisa — sekarang waktunya naik level! Pelajari cara menyambungkan tiga tabel atau lebih dalam satu query yang rapi, efisien, dan mudah dibaca.

4
Pola JOIN
9+
Contoh Query
13
Menit Baca
5
Langkah Praktik

Pernah beli barang online, terus kamu bisa lihat nama kamu, nama produknya, kategori produk, nama kurir, hingga nama kota pengiriman — semua dalam satu halaman? Di balik tampilan itu, ada satu query SQL yang menyatukan empat atau lima tabel sekaligus. Itulah kekuatan multi table JOIN MySQL yang akan kita bahas di artikel ke-22 dari seri 28 artikel Belajar Query SQL MySQL ini!

Kalau di artikel sebelumnya kamu sudah paham LEFT JOIN, RIGHT JOIN, dan CROSS JOIN antara dua tabel — sekarang kita naik level. Dunia nyata jarang punya cuma dua tabel. Aplikasi toko online yang serius bisa punya belasan tabel yang saling terhubung, dan kamu perlu bisa menarik data dari semuanya dalam satu query yang bersih dan efisien.

Di artikel ini kita akan belajar: cara menyusun multi-table JOIN, urutan tabel yang benar, menghindari jebakan alias yang bikin error, dan contoh query nyata dari studi kasus toko online kita. Siap? Mari mulai!

๐Ÿคฏ
Fakta Menarik

Sistem ERP (Enterprise Resource Planning) seperti SAP atau Odoo yang digunakan perusahaan besar seringkali memiliki query dengan 10–20 tabel yang di-JOIN sekaligus. Seorang DBA (Database Administrator) senior wajib bisa membaca dan mengoptimasi query raksasa seperti itu. Fondasi dasarnya? Persis yang kamu pelajari sekarang!

01. Konsep Dasar: Rantai JOIN

Analogi: Bayangkan kamu mau trace sebuah paket pengiriman. Kamu mulai dari struk belanja (pesanan), lalu cocokkan dengan buku produk (tabel produk), kemudian cocokkan lagi dengan data pelanggan (tabel pelanggan), dan terakhir dengan catatan pengiriman (tabel pengiriman). Kamu berpindah dari satu buku ke buku lain secara berantai — itulah multi-table JOIN!

MySQL memproses JOIN dari kiri ke kanan secara berurutan. Setiap JOIN menambahkan tabel baru ke hasil sementara yang sudah ada. Jadi multi table JOIN MySQL pada dasarnya adalah tumpukan JOIN — satu di atas yang lain.

๐Ÿ“ Sintaks Lengkap Multi-Table JOIN
SELECT
  t1.kolom_a,          -- kolom dari tabel pertama
  t2.kolom_b,          -- kolom dari tabel kedua
  t3.kolom_c,          -- kolom dari tabel ketiga
  t4.kolom_d           -- kolom dari tabel keempat (dst)

FROM       tabel1 t1           -- tabel utama (anchor/basis)

INNER JOIN tabel2 t2           -- JOIN tabel kedua
  ON       t1.id = t2.fk_id   -- kondisi relasi tabel1 ↔ tabel2

INNER JOIN tabel3 t3           -- JOIN tabel ketiga ke hasil sebelumnya
  ON       t2.id = t3.fk_id   -- kondisi relasi tabel2 ↔ tabel3

LEFT JOIN  tabel4 t4           -- bisa campur jenis JOIN!
  ON       t3.id = t4.fk_id   -- kondisi relasi tabel3 ↔ tabel4

WHERE      t1.kolom = 'nilai'  -- filter opsional
ORDER BY   t1.kolom_a;         -- urutan opsional
๐Ÿ’ก Poin Kunci

Kamu tidak wajib pakai jenis JOIN yang sama untuk setiap JOIN. Dalam satu query, kamu bisa campur INNER JOIN dan LEFT JOIN sesuai kebutuhan. Tabel yang datanya wajib ada? Pakai INNER JOIN. Tabel yang opsional? Pakai LEFT JOIN.

Setup Data Toko Online (4 Tabel):

-- Tabel 1: pelanggan
CREATE TABLE pelanggan (
  id_pelanggan INT PRIMARY KEY,
  nama         VARCHAR(100),
  kota         VARCHAR(50)
);
INSERT INTO pelanggan VALUES
  (1,'Andi','Jakarta'),(2,'Budi','Bandung'),(3,'Citra','Surabaya');

-- Tabel 2: kategori
CREATE TABLE kategori (
  id_kategori  INT PRIMARY KEY,
  nama_kategori VARCHAR(50)
);
INSERT INTO kategori VALUES
  (1,'Elektronik'),(2,'Aksesoris'),(3,'Peripheral');

-- Tabel 3: produk (relasi ke kategori)
CREATE TABLE produk (
  id_produk    INT PRIMARY KEY,
  nama_produk  VARCHAR(100),
  id_kategori  INT,
  harga        INT
);
INSERT INTO produk VALUES
  (1,'Laptop Gaming',1,15000000),
  (2,'Mouse Wireless',2,250000),
  (3,'Mechanical Keyboard',3,750000),
  (4,'Monitor 4K',1,5000000);

-- Tabel 4: pesanan (relasi ke pelanggan & produk)
CREATE TABLE pesanan (
  id_pesanan   INT PRIMARY KEY,
  id_pelanggan INT,
  id_produk    INT,
  jumlah       INT,
  tanggal      DATE
);
INSERT INTO pesanan VALUES
  (101,1,1,1,'2024-01-15'),
  (102,2,2,2,'2024-01-16'),
  (103,1,3,1,'2024-01-17'),
  (104,3,4,1,'2024-01-18'),
  (105,2,1,1,'2024-01-19');

02. JOIN 3 Tabel: Pesanan + Pelanggan + Produk

Kasus paling umum dalam multi table JOIN MySQL adalah laporan yang butuh info dari tiga tabel: kita mau tahu siapa yang memesan (pelanggan), apa yang dipesan (produk), dan kapan dipesan (pesanan). Tabel pesanan menjadi jembatan — karena dia punya id_pelanggan dan id_produk sekaligus.

-- Laporan pesanan lengkap (3 tabel)
SELECT
  ps.id_pesanan,
  ps.tanggal,
  pl.nama            AS nama_pelanggan,
  pl.kota,
  pr.nama_produk,
  ps.jumlah,
  pr.harga,
  (ps.jumlah * pr.harga) AS total_bayar

FROM       pesanan ps               -- tabel anchor/utama

INNER JOIN pelanggan pl             -- JOIN tabel pelanggan
  ON       ps.id_pelanggan = pl.id_pelanggan

INNER JOIN produk pr               -- JOIN tabel produk
  ON       ps.id_produk = pr.id_produk

ORDER BY   ps.tanggal;
๐Ÿ“Š Hasil Query (JOIN 3 Tabel):
id_pesanan tanggal nama_pelanggan kota nama_produk jumlah total_bayar
1012024-01-15AndiJakartaLaptop Gaming115.000.000
1022024-01-16BudiBandungMouse Wireless2500.000
1032024-01-17AndiJakartaMechanical Keyboard1750.000
1042024-01-18CitraSurabayaMonitor 4K15.000.000
1052024-01-19BudiBandungLaptop Gaming115.000.000

⬆️ Kolom total_bayar dihitung langsung di SELECT — kamu bisa bikin kolom kalkulasi langsung dalam query tanpa perlu tabel baru!

✅ Tip Praktis

Jadikan tabel yang menjadi penghubung antar tabel lain (seperti tabel pesanan yang punya FK ke mana-mana) sebagai tabel utama di klausa FROM. Ini membuat alur join lebih logis dan mudah diikuti.

03. JOIN 4 Tabel: Tambahkan Kategori Produk

Sekarang kita tambah satu tabel lagi — kategori — agar di laporan muncul nama kategori produk, bukan cuma nama produknya. Ini adalah contoh klasik multi table JOIN MySQL empat tabel, yang sering muncul di tugas akhir dan proyek kampus.

Perhatikan urutannya: pesanan → pelanggan → produk → kategori. Setiap JOIN harus "masuk akal" — relasi antara tabel yang sedang di-JOIN dan hasil gabungan sebelumnya harus jelas.

-- Laporan lengkap dengan kategori (4 tabel)
SELECT
  ps.id_pesanan,
  ps.tanggal,
  pl.nama              AS pelanggan,
  pl.kota,
  k.nama_kategori      AS kategori,    -- dari tabel kategori
  pr.nama_produk,
  pr.harga,
  ps.jumlah,
  (ps.jumlah * pr.harga) AS subtotal

FROM       pesanan ps

INNER JOIN pelanggan pl
  ON       ps.id_pelanggan = pl.id_pelanggan

INNER JOIN produk pr
  ON       ps.id_produk = pr.id_produk

INNER JOIN kategori k             -- JOIN ke tabel kategori lewat produk
  ON       pr.id_kategori = k.id_kategori

ORDER BY   k.nama_kategori, ps.tanggal;
๐Ÿ“Š Hasil Query (JOIN 4 Tabel — diurutkan per kategori):
id tanggal pelanggan kota kategori nama_produk subtotal
1022024-01-16BudiBandungAksesorisMouse Wireless500.000
1012024-01-15AndiJakartaElektronikLaptop Gaming15.000.000
1042024-01-18CitraSurabayaElektronikMonitor 4K5.000.000
1052024-01-19BudiBandungElektronikLaptop Gaming15.000.000
1032024-01-17AndiJakartaPeripheralMechanical Keyboard750.000
⚠️ Jangan Lupa!

Kondisi ON di setiap JOIN harus merujuk ke tabel yang sudah ada di hasil JOIN sebelumnya atau tabel yang baru dimasukkan. Kamu tidak bisa merujuk tabel yang belum di-JOIN. Urutan JOIN menentukan tabel mana yang "tersedia" di kondisi ON berikutnya.

04. Jebakan Umum & Cara Menghindarinya

Semakin banyak tabel yang di-JOIN, semakin banyak peluang untuk error atau hasil yang tidak terduga. Ini tiga jebakan paling sering dialami mahasiswa saat pertama kali mencoba multi table JOIN MySQL:

❌ SALAH — Kolom Ambigu (Ambiguous Column)
SELECT nama, nama_produk, harga  -- "nama" ada di tabel pelanggan DAN produk!
FROM pesanan
INNER JOIN pelanggan ON pesanan.id_pelanggan = pelanggan.id_pelanggan
INNER JOIN produk ON pesanan.id_produk = produk.id_produk;
-- ERROR: Column 'nama' in field list is ambiguous
✅ BENAR — Selalu Prefix dengan Alias Tabel
SELECT
  pl.nama        AS nama_pelanggan,  -- eksplisit: dari tabel pelanggan
  pr.nama_produk,                     -- dari tabel produk
  pr.harga
FROM       pesanan ps
INNER JOIN pelanggan pl ON ps.id_pelanggan = pl.id_pelanggan
INNER JOIN produk pr    ON ps.id_produk = pr.id_produk;
-- ✓ Query berjalan dengan benar
๐Ÿ“Š Hasil Setelah Diperbaiki:
nama_pelanggan nama_produk harga
AndiLaptop Gaming15.000.000
BudiMouse Wireless250.000
AndiMechanical Keyboard750.000
CitraMonitor 4K5.000.000
BudiLaptop Gaming15.000.000
⚠️ Aturan Emas Multi-Table JOIN

Selalu gunakan alias tabel yang pendek dan konsisten. Jangan pernah sebutkan nama kolom tanpa prefix alias ketika JOIN lebih dari satu tabel — bahkan jika kamu "yakin" nama kolomnya unik. Kebiasaan ini menyelamatkan kamu dari berjam-jam debugging!

๐Ÿงช Panduan Praktikum Step-by-Step

1
Buat Database & Jalankan Script Setup

Buka MySQL Workbench, buat database baru, dan jalankan semua CREATE TABLE + INSERT INTO dari bagian setup di atas.

CREATE DATABASE toko_online_v2;
USE toko_online_v2;
-- Lalu jalankan semua script setup di atas
2
Verifikasi Semua Tabel

Cek setiap tabel sebelum mulai JOIN — pastikan data sudah masuk dengan benar.

SELECT * FROM pelanggan; -- 3 baris
SELECT * FROM kategori; -- 3 baris
SELECT * FROM produk; -- 4 baris
SELECT * FROM pesanan; -- 5 baris
3
Mulai dengan JOIN 2 Tabel Dulu

Jangan langsung JOIN 4 tabel. Mulai dari 2 tabel, pastikan hasilnya benar, baru tambah JOIN berikutnya satu per satu.

SELECT ps.id_pesanan, pl.nama
FROM pesanan ps
INNER JOIN pelanggan pl
ON ps.id_pelanggan = pl.id_pelanggan;
-- Cek: 5 baris? Bagus, lanjut tambah JOIN ketiga
4
Tambah JOIN Ketiga (Produk) & Cek Hasilnya

Setelah JOIN 2 tabel berhasil, tambahkan INNER JOIN produk. Jumlah baris seharusnya tetap 5 (karena semua pesanan punya produk yang valid).

5
Tambah JOIN Keempat (Kategori) & Buat Laporan Lengkap

Setelah 3 tabel sukses, sambungkan tabel kategori lewat produk. Tambahkan kolom kalkulasi dan ORDER BY untuk laporan profesional.

-- Filter hanya pembelian dari Jakarta
WHERE pl.kota = 'Jakarta'
-- Harusnya muncul 2 baris (pesanan Andi)

๐Ÿ“‹ Ringkasan: Pola Multi-Table JOIN

Skenario Pola JOIN Cocok Untuk Risiko
2 tabel wajib ada INNER JOIN INNER JOIN Laporan yang butuh data valid semua tabel Rendah
1 tabel opsional INNER JOIN LEFT JOIN Data utama wajib, data tambahan boleh kosong Rendah
Semua opsional LEFT JOIN LEFT JOIN Rekap komprehensif dengan banyak NULL Sedang
Self JOIN tabel JOIN tabel AS alias Hierarki dalam satu tabel (atasan-bawahan) Sedang
5+ tabel Campuran sesuai kebutuhan Sistem ERP, laporan kompleks Tinggi (perlu index!)
๐ŸŽ“ Insight Trainer

Di dunia kerja, developer sering membangun query multi-table JOIN secara incremental — tambahkan satu JOIN, cek hasilnya, baru tambah lagi. Jangan langsung tulis 5 JOIN sekaligus kalau belum yakin relasi antar tabelnya!

๐Ÿ’ก Tip Performa

Semakin banyak tabel yang di-JOIN, semakin penting untuk punya INDEX pada kolom yang dipakai di kondisi ON. Tanpa index, MySQL harus scan seluruh tabel untuk setiap baris — bisa sangat lambat di data besar!

✅ Kesimpulan

  • Multi table JOIN MySQL adalah kemampuan menggabungkan tiga tabel atau lebih dalam satu query menggunakan klausa JOIN yang dirantai secara berurutan.
  • Setiap JOIN ditambahkan setelah yang sebelumnya — MySQL memproses dari kiri ke kanan, membangun hasil sementara di setiap tahap.
  • Alias tabel bukan opsional — di multi-table JOIN, alias adalah wajib untuk menghindari ambiguitas kolom dan membuat query mudah dibaca.
  • Kamu bisa campur jenis JOIN (INNER dan LEFT) dalam satu query sesuai apakah tabel tersebut wajib ada datanya atau opsional.
  • Bangun query secara incremental — mulai dari 2 tabel, verifikasi, baru tambah JOIN berikutnya. Hindari menulis 5 JOIN sekaligus tanpa mengecek tiap tahapnya.
  • Untuk multi table JOIN MySQL di data besar, selalu pastikan ada INDEX pada kolom yang dipakai sebagai kondisi ON untuk performa optimal.

"Database yang baik adalah yang bisa bercerita. Dan multi-table JOIN adalah cara kamu membuat semua tabel bercerita bersama-sama dalam satu kalimat yang kohesif. Kuasai ini, dan kamu selangkah lebih dekat jadi database developer yang sesungguhnya. ๐Ÿš€"

๐Ÿ’ฌ Sudah coba JOIN lebih dari 3 tabel?

Ceritakan pengalaman kamu di kolom komentar — berhasil langsung atau ada yang bikin pusing dulu? Kalau artikel ini berguna, share ke teman satu kelas dan bookmark halaman ini untuk referensi tugas! ⭐

๐Ÿ“– Artikel Berikutnya (23/28)
Subquery & Nested Query di MySQL

Menyarangkan query di dalam query lain — teknik powerful untuk analisis data yang lebih kompleks dan fleksibel!

Baca Sekarang →
MySQL SQL Database Query Tutorial multi table JOIN MySQL JOIN 4 Tabel Belajar MySQL

saifiahmada.com adalah blog belajar programming Indonesia, membahas lengkap materi bahasa pemrograman: code HTML, CSS, Bootstrap, Desain, PHP, MySQL, coding Java, Query, SQL, dan dunia linux