Belajar SQL JOIN
19 October 2026 • 21 menit baca • query laporan penjualan, SQL JOIN, INNER JOIN SQL, LEFT JOIN SQL, contoh query JOIN, relasi antar tabel database, belajar SQL untuk pemula
Belajar SQL JOIN untuk Pemula: INNER JOIN, LEFT JOIN, dan Contoh Query
Pernahkah kamu membuka laporan penjualan sebuah toko online, lalu ingin mengetahui nama pelanggan, tanggal transaksi, nama produk yang dibeli, dan total pembayaran dalam satu laporan?
Masalahnya, informasi tersebut tidak selalu tersimpan dalam satu tabel. Nama pelanggan mungkin berada di tabel customers, tanggal transaksi berada di tabel orders, sedangkan nama produk dan harganya berada di tabel products.
Apakah kita harus membuka tabel satu per satu dan mencocokkan datanya secara manual?
Tentu tidak. Di sinilah SQL JOIN digunakan.
Melalui artikel ini, kita akan belajar memahami fungsi JOIN, mengenal INNER JOIN dan LEFT JOIN, menggabungkan tiga tabel atau lebih, hingga membuat laporan penjualan menggunakan MySQL 8.4.
Kita akan melanjutkan cerita TokoKita dari artikel sebelumnya agar setiap query terasa seperti menyelesaikan masalah nyata, bukan sekadar menghafalkan sintaks.
1. Mengapa Kita Membutuhkan SQL JOIN?
Bayangkan TokoKita mulai berkembang. Awalnya, toko hanya memiliki beberapa produk. Namun, sekarang pelanggan semakin banyak dan transaksi terjadi setiap hari.
Pemilik toko ingin menjawab beberapa pertanyaan:
- Siapa nama pelanggan yang melakukan transaksi?
- Produk apa saja yang mereka beli?
- Berapa jumlah produk yang dibeli?
- Kapan transaksi terjadi?
- Pelanggan mana yang belum pernah melakukan pembelian?
Informasi tersebut tersebar di beberapa tabel.
Misalnya, tabel pelanggan hanya menyimpan identitas pelanggan. Tabel pesanan menyimpan informasi transaksi, sedangkan tabel produk menyimpan katalog barang.
Jika kita menjalankan query berikut:
SELECT *
FROM customers;Kita hanya mendapatkan informasi dari tabel pelanggan.
Begitu juga jika menjalankan:
SELECT *
FROM orders;Kita hanya mendapatkan informasi pesanan, bukan otomatis memperoleh nama pelanggan atau nama produknya.
SQL JOIN memungkinkan kita menggabungkan baris dari dua tabel atau lebih berdasarkan kondisi hubungan tertentu. Dalam praktiknya, kondisi tersebut biasanya menggunakan kolom kunci seperti customer_id atau product_id.
Dengan demikian, kita bisa membuat laporan yang lebih informatif tanpa harus menyimpan seluruh informasi berulang kali dalam satu tabel.
2. Memahami Struktur Database TokoKita
Sebelum menulis query JOIN, kita perlu memahami tabel yang akan dihubungkan.
Untuk latihan ini, TokoKita menggunakan empat tabel:
<box>
<title size="md">Relasi tabel TokoKita</title>
<box border radius="lg" padding={3} gap={1}> <row align="center" gap={2}> <icon name="users" size="xl" />
<box flex="1" gap={1}> **customers** <text color="secondary" size="sm">Data pelanggan</text>
<text size="sm">PK: `id`</text> </box> </row>
<divider color="subtle" /> <row align="center" gap={2}>
<icon name="shopping-cart" size="xl" />
<box flex="1" gap={1}> **orders** <text color="secondary" size="sm">Data pesanan pelanggan</text>
<text size="sm">PK: `id` · FK: `customer_id`</text>
</box> </row> <divider color="subtle" /> <row align="center" gap={2}>
<icon name="package" size="xl" /> <box flex="1" gap={1}> **order_items** <text color="secondary" size="sm">Detail produk pada setiap pesanan</text> <text size="sm">FK: `order_id`, `product_id`</text> </box> </row>
<divider color="subtle" />
<row align="center" gap={2}>
<icon name="boxes" size="xl" />
<box flex="1" gap={1}> **products** <text color="secondary" size="sm">Katalog produk</text>
<text size="sm">PK: `id`</text>
</box> </row> </box>
<text color="secondary" size="xs">PK berarti Primary Key, sedangkan FK berarti Foreign Key. Diagram ini menggambarkan hubungan logis antartabel.</text> </box>
Apa itu Primary Key dan Foreign Key?
Primary Key (PK) adalah kolom yang mengidentifikasi setiap baris secara unik dalam sebuah tabel. Contohnya, customers.id.
Foreign Key (FK) adalah kolom yang merujuk pada kunci di tabel lain untuk merepresentasikan hubungan antardata. Contohnya, orders.customer_id merujuk pada customers.id.
Keduanya membantu kita menentukan bagaimana data harus dihubungkan. Pada MySQL, foreign key juga dapat digunakan untuk menjaga konsistensi hubungan antartabel. Namun, query JOIN tetap harus menuliskan kondisi penggabungan yang tepat.
Dokumentasi resmi: MySQL — FOREIGN KEY Constraints.
2.1. Tabel customers
Tabel ini menyimpan informasi pelanggan.
| id | name | city |
|---|---|---|
| 1 | Andi | Jakarta |
| 2 | Budi | Bandung |
| 3 | Citra | Surabaya |
| 4 | Dewi | Depok |
2.2. Tabel orders
Tabel ini menyimpan pesanan yang dibuat pelanggan.
| id | customer_id | order_date | status |
|---|---|---|---|
| 101 | 1 | 2026-10-01 | completed |
| 102 | 2 | 2026-10-02 | completed |
| 103 | 1 | 2026-10-04 | pending |
| 104 | 3 | 2026-10-05 | completed |
Perhatikan kolom customer_id. Angka tersebut menghubungkan pesanan dengan pelanggan.
Sebagai contoh, pesanan 101 memiliki customer_id = 1. Artinya, pesanan tersebut milik pelanggan dengan id = 1, yaitu Andi.
2.3. Tabel products
Tabel ini menyimpan daftar produk yang dijual TokoKita.
| id | product_name | price |
|---|---|---|
| 201 | Keyboard | 450000 |
| 202 | Mouse | 175000 |
| 203 | Monitor | 1850000 |
| 204 | USB Hub | 125000 |
2.4. Tabel order_items
Tabel ini menyimpan detail barang yang terdapat di dalam setiap pesanan.
| id | order_id | product_id | quantity |
|---|---|---|---|
| 1 | 101 | 201 | 2 |
| 2 | 101 | 202 | 1 |
| 3 | 102 | 203 | 1 |
| 4 | 103 | 204 | 3 |
| 5 | 104 | 202 | 2 |
Mengapa tidak langsung memasukkan nama produk ke tabel orders?
Karena satu pesanan bisa berisi beberapa produk. Dengan memisahkan detail pesanan ke dalam order_items, struktur data menjadi lebih fleksibel.
Dari contoh tersebut, kita juga bisa melihat bahwa pelanggan Dewi belum memiliki pesanan. Informasi ini akan berguna ketika mempelajari LEFT JOIN.
3. Apa Itu SQL JOIN?
Secara sederhana, JOIN adalah cara untuk menggabungkan informasi dari beberapa tabel berdasarkan kondisi tertentu.
Bentuk umum query-nya adalah:
SELECT
kolom_tabel_pertama,
kolom_tabel_kedua
FROM tabel_pertama
JOIN tabel_kedua
ON tabel_pertama.kolom_kunci =
tabel_kedua.kolom_kunci;Ada tiga bagian penting:
SELECT: menentukan kolom yang ingin ditampilkan.JOIN: menentukan tabel yang ingin digabungkan.ON: menentukan kondisi untuk mencocokkan baris dari kedua tabel.
Contohnya, kita ingin menampilkan pesanan beserta nama pelanggan.
SELECT
orders.id AS order_id,
customers.name AS customer_name,
orders.order_date,
orders.status
FROM orders
INNER JOIN customers
ON orders.customer_id = customers.id;Query tersebut menghubungkan orders.customer_id dengan customers.id.
Kita menggunakan nama tabel sebelum nama kolom supaya sumber setiap kolom jelas. Ini penting ketika dua tabel mempunyai kolom dengan nama yang sama, misalnya id.
Hasilnya akan berisi informasi pesanan beserta nama pelanggannya.
| order_id | customer_name | order_date | status |
|---|---|---|---|
| 101 | Andi | 2026-10-01 | completed |
| 102 | Budi | 2026-10-02 | completed |
| 103 | Andi | 2026-10-04 | pending |
| 104 | Citra | 2026-10-05 | completed |
Nama pelanggan Dewi tidak muncul karena kita menggunakan INNER JOIN, sementara Dewi belum memiliki pesanan.
Mari kita pelajari alasannya.
4. INNER JOIN: Mengambil Data yang Cocok di Kedua Tabel
INNER JOIN mengambil baris yang memiliki pasangan sesuai kondisi ON pada kedua tabel.
Bayangkan kita memiliki daftar pelanggan dan daftar pesanan. Jika kita hanya ingin melihat pelanggan yang benar-benar mempunyai pesanan, INNER JOIN adalah pilihan yang tepat.
4.1. Contoh query INNER JOIN
SELECT
c.id AS customer_id,
c.name AS customer_name,
o.id AS order_id,
o.order_date
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id;Hasilnya:
| customer_id | customer_name | order_id | order_date |
|---|---|---|---|
| 1 | Andi | 101 | 2026-10-01 |
| 1 | Andi | 103 | 2026-10-04 |
| 2 | Budi | 102 | 2026-10-02 |
| 3 | Citra | 104 | 2026-10-05 |
Mengapa Andi muncul dua kali?
Karena Andi memiliki dua pesanan. Setiap baris pesanan yang cocok menghasilkan baris hasil tersendiri.
Mengapa Dewi tidak muncul?
Karena tidak ditemukan baris pesanan yang cocok dengan customers.id = 4.
Hal ini bukan kesalahan. Memang seperti itulah cara kerja INNER JOIN.
4.2. Kapan INNER JOIN digunakan?
Gunakan INNER JOIN ketika kamu hanya membutuhkan data yang memiliki pasangan di kedua tabel.
Contohnya:
- Menampilkan pesanan beserta nama pelanggannya.
- Menampilkan detail transaksi beserta nama produknya.
- Menampilkan karyawan beserta nama departemen yang terhubung.
- Menampilkan pembayaran yang memiliki transaksi terkait.
Ingat, hasil JOIN tidak selalu memiliki jumlah baris yang sama dengan tabel awal. Jika satu pelanggan memiliki banyak pesanan, pelanggan tersebut dapat muncul berkali-kali.
5. LEFT JOIN: Mempertahankan Semua Data dari Tabel Kiri
Sekarang pemilik TokoKita ingin mengetahui seluruh pelanggan, termasuk pelanggan yang belum pernah melakukan pembelian.
Jika kita tetap menggunakan INNER JOIN, pelanggan tanpa pesanan tidak akan muncul.
Untuk kebutuhan ini, kita dapat menggunakan LEFT JOIN.
LEFT JOIN mempertahankan semua baris dari tabel di sebelah kiri. Jika tidak ada pasangan di tabel kanan, kolom dari tabel kanan akan berisi NULL.
5.1. Contoh query LEFT JOIN
SELECT
c.id AS customer_id,
c.name AS customer_name,
o.id AS order_id,
o.order_date
FROM customers AS c
LEFT JOIN orders AS o
ON c.id = o.customer_id;Hasilnya:
| customer_id | customer_name | order_id | order_date |
|---|---|---|---|
| 1 | Andi | 101 | 2026-10-01 |
| 1 | Andi | 103 | 2026-10-04 |
| 2 | Budi | 102 | 2026-10-02 |
| 3 | Citra | 104 | 2026-10-05 |
| 4 | Dewi | NULL | NULL |
Dewi sekarang muncul meskipun belum memiliki pesanan.
Nilai NULL pada order_id dan order_date berarti tidak ada baris pesanan yang cocok untuk Dewi dalam hasil penggabungan tersebut. Nilai ini bukan angka nol dan bukan teks kosong.
5.2. Kapan LEFT JOIN digunakan?
Contoh penggunaan LEFT JOIN:
- Menampilkan semua pelanggan beserta riwayat pesanannya.
- Menampilkan semua produk, termasuk produk yang belum pernah terjual.
- Menampilkan seluruh karyawan meskipun sebagian belum memiliki catatan tertentu.
- Mencari pelanggan yang belum pernah melakukan transaksi.
5.3. Mencari pelanggan yang belum pernah memesan
Sekarang kita ingin membuat laporan khusus pelanggan yang belum pernah membeli.
Kita bisa menggunakan LEFT JOIN lalu memeriksa baris yang tidak memiliki pasangan.
SELECT
c.id,
c.name,
c.city
FROM customers AS c
LEFT JOIN orders AS o
ON c.id = o.customer_id
WHERE o.id IS NULL;Hasilnya:
| id | name | city |
|---|---|---|
| 4 | Dewi | Depok |
Mengapa WHERE o.id IS NULL?
Karena orders.id seharusnya memiliki nilai untuk setiap pesanan yang benar-benar ada. Ketika tidak ditemukan pesanan, kolom tersebut menjadi NULL pada hasil LEFT JOIN.
Teknik ini sering disebut anti-join pattern: mencari data dari tabel utama yang tidak memiliki pasangan pada tabel lain.
6. Perbedaan INNER JOIN dan LEFT JOIN
| Aspek | INNER JOIN | LEFT JOIN |
|---|---|---|
| Baris tabel kiri tanpa pasangan | Tidak ditampilkan | Tetap ditampilkan |
| Kolom tabel kanan tanpa pasangan | Tidak ada baris hasilnya | Bernilai NULL |
| Cocok untuk | Data yang memiliki pasangan | Semua data utama, termasuk yang tidak memiliki pasangan |
| Contoh | Pesanan dengan pelanggan | Semua pelanggan, termasuk yang belum memesan |
Cara mudah mengingatnya:
INNER JOIN: tampilkan yang cocok.LEFT JOIN: pertahankan semua baris dari tabel kiri, lalu tambahkan data yang cocok dari tabel kanan jika tersedia.
7. Memahami Alias Tabel: c, o, p, dan oi
Ketika query mulai menggabungkan banyak tabel, menuliskan nama tabel lengkap berulang kali dapat membuat query panjang.
Karena itu, kita bisa menggunakan alias.
Contoh:
SELECT
c.name,
o.order_date
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id;Pada query tersebut:
cadalah alias untukcustomers.oadalah alias untukorders.
Alias AS boleh ditulis atau dihilangkan dalam deklarasi alias tabel pada MySQL. Namun, menggunakan AS bisa membuat query lebih mudah dibaca oleh pemula.
Alias tidak mengubah nama tabel asli. Alias hanya menjadi nama singkat untuk merujuk tabel selama query berjalan.
Biasakan menuliskan kolom dengan format alias.nama_kolom, khususnya ketika beberapa tabel mempunyai kolom bernama id, name, atau status.
8. Menggabungkan Tiga Tabel dengan JOIN
Sekarang kita naik satu tingkat.
Pemilik TokoKita tidak hanya ingin mengetahui siapa yang melakukan pesanan. Ia juga ingin mengetahui produk apa saja yang dibeli setiap pelanggan.
Informasi ini membutuhkan tiga tabel:
customersuntuk nama pelanggan.ordersuntuk data pesanan.order_itemsuntuk detail produk di dalam pesanan.
Kita bisa menggabungkan ketiganya melalui dua kondisi hubungan.
SELECT
c.name AS customer_name,
o.id AS order_id,
oi.product_id,
oi.quantity
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id
INNER JOIN order_items AS oi
ON o.id = oi.order_id
ORDER BY o.id, oi.id;Hasilnya:
| customer_name | order_id | product_id | quantity |
|---|---|---|---|
| Andi | 101 | 201 | 2 |
| Andi | 101 | 202 | 1 |
| Budi | 102 | 203 | 1 |
| Andi | 103 | 204 | 3 |
| Citra | 104 | 202 | 2 |
Sekarang kita bisa melihat produk yang terdapat pada setiap pesanan. Namun, hasil tersebut masih menampilkan product_id, bukan nama produk.
Untuk mendapatkan nama produk, kita perlu menggabungkan satu tabel lagi.
9. Menggabungkan Empat Tabel untuk Laporan Penjualan
Inilah contoh yang lebih mendekati laporan aplikasi bisnis sesungguhnya.
Kita ingin menampilkan:
- Nama pelanggan.
- Nomor pesanan.
- Tanggal transaksi.
- Nama produk.
- Jumlah produk.
- Harga satuan.
- Subtotal setiap baris detail pesanan.
Query-nya:
SELECT
c.name AS customer_name,
o.id AS order_id,
o.order_date,
p.product_name,
oi.quantity,
p.price AS unit_price,
oi.quantity * p.price AS subtotal
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id
INNER JOIN order_items AS oi
ON o.id = oi.order_id
INNER JOIN products AS p
ON oi.product_id = p.id
ORDER BY o.id, oi.id;Mari kita uraikan jalur hubungannya:
customersdihubungkan denganordersmelaluic.id = o.customer_id.ordersdihubungkan denganorder_itemsmelaluio.id = oi.order_id.order_itemsdihubungkan denganproductsmelaluioi.product_id = p.id.
Hasilnya:
| customer_name | order_id | product_name | quantity | unit_price | subtotal |
|---|---|---|---|---|---|
| Andi | 101 | Keyboard | 2 | 450000 | 900000 |
| Andi | 101 | Mouse | 1 | 175000 | 175000 |
| Budi | 102 | Monitor | 1 | 1850000 | 1850000 |
| Andi | 103 | USB Hub | 3 | 125000 | 375000 |
| Citra | 104 | Mouse | 2 | 175000 | 350000 |
Perhatikan baris pertama: Andi membeli dua Keyboard dengan harga satuan Rp450.000. Subtotalnya adalah:
2 × Rp450.000 = Rp900.000
Perhitungan ini menggunakan harga yang saat ini tersimpan pada tabel products. Pada sistem transaksi produksi, harga produk saat transaksi sebaiknya juga disimpan sebagai snapshot di order_items, misalnya unit_price, agar perubahan harga katalog di kemudian hari tidak mengubah perhitungan historis transaksi.
Mengapa urutan JOIN penting untuk dipahami?
Secara logis, kita mengikuti hubungan data dari pelanggan ke pesanan, kemudian ke detail pesanan dan produk. Urutan ini membantu kita memahami relasi serta menuliskan kondisi ON yang benar.
MySQL memiliki optimizer yang dapat menentukan strategi eksekusi query. Jadi, urutan penulisan tabel tidak selalu berarti database membaca data persis dalam urutan tersebut.
Yang lebih penting bagi pemula adalah memastikan setiap tabel dihubungkan melalui kolom yang benar.
10. Menggabungkan JOIN dengan WHERE
JOIN tidak menggantikan WHERE. Keduanya memiliki fungsi berbeda dan dapat digunakan bersama.
ONmenentukan kondisi pencocokan antartabel.WHEREmenyaring baris hasil berdasarkan kriteria yang kita inginkan.
Misalnya, pemilik TokoKita ingin melihat transaksi yang berstatus completed.
SELECT
c.name AS customer_name,
o.id AS order_id,
o.order_date,
o.status
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id
WHERE o.status = 'completed'
ORDER BY o.order_date DESC;Query ini menggabungkan pelanggan dengan pesanan, lalu hanya menampilkan pesanan yang sudah selesai.
Kita juga bisa menggunakan kondisi tanggal:
SELECT
c.name AS customer_name,
o.id AS order_id,
o.order_date
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id
WHERE o.order_date >= '2026-10-01'
AND o.order_date < '2026-11-01';Rentang tersebut mengambil pesanan mulai 1 Oktober 2026 sampai sebelum 1 November 2026. Pola ini berguna untuk membuat laporan bulanan tanpa harus bergantung pada komponen waktu jika kolom nantinya bertipe DATETIME.
11. Perbedaan ON dan WHERE pada LEFT JOIN
Bagian ini sangat penting karena kesalahan kecil dapat mengubah hasil laporan.
Misalnya, kita ingin menampilkan semua pelanggan dan pesanan mereka jika pesanan tersebut sudah selesai. Pelanggan tanpa pesanan selesai tetap harus muncul.
Salah satu cara menuliskannya adalah:
SELECT
c.name AS customer_name,
o.id AS order_id,
o.status
FROM customers AS c
LEFT JOIN orders AS o
ON c.id = o.customer_id
AND o.status = 'completed';Kondisi status diletakkan pada ON. Dengan demikian, tabel customers tetap dipertahankan, sedangkan hanya pesanan yang berstatus completed yang menjadi pasangan.
Sebaliknya, perhatikan query berikut:
SELECT
c.name AS customer_name,
o.id AS order_id,
o.status
FROM customers AS c
LEFT JOIN orders AS o
ON c.id = o.customer_id
WHERE o.status = 'completed';Query kedua hanya menampilkan baris yang memenuhi kondisi status di WHERE. Baris pelanggan yang tidak memiliki pesanan akan memiliki o.status = NULL dan tidak lolos kondisi tersebut.
Akibatnya, perilaku query menjadi mirip INNER JOIN untuk filter status ini: pelanggan tanpa pesanan selesai tidak dipertahankan.
Prinsip praktisnya: jika ingin mempertahankan semua baris tabel kiri, pikirkan baik-baik apakah filter tabel kanan harus ditempatkan di ON atau di WHERE.
12. Menggabungkan JOIN dengan Fungsi Agregasi
Pada artikel sebelumnya, kita mempelajari COUNT(), SUM(), AVG(), dan GROUP BY. Sekarang kita dapat menggunakan kemampuan tersebut bersama JOIN.
Misalnya, TokoKita ingin mengetahui total pesanan yang dimiliki setiap pelanggan.
SELECT
c.id,
c.name AS customer_name,
COUNT(o.id) AS total_orders
FROM customers AS c
LEFT JOIN orders AS o
ON c.id = o.customer_id
GROUP BY
c.id,
c.name
ORDER BY total_orders DESC;Hasilnya:
| id | customer_name | total_orders |
|---|---|---|
| 1 | Andi | 2 |
| 2 | Budi | 1 |
| 3 | Citra | 1 |
| 4 | Dewi | 0 |
Mengapa kita menggunakan COUNT(o.id), bukan COUNT(*)?
Pada LEFT JOIN, pelanggan tanpa pesanan tetap menghasilkan satu baris hasil dengan kolom dari tabel orders bernilai NULL.
COUNT(*)menghitung baris hasil, termasuk baris pelanggan tanpa pasangan.COUNT(o.id)hanya menghitung nilaio.idyang tidakNULL.
Karena itu, COUNT(o.id) memberikan angka nol untuk Dewi.
12.1. Menghitung jumlah produk yang dibeli pelanggan
Kita juga dapat menghitung total unit produk yang terdapat dalam pesanan setiap pelanggan.
SELECT
c.name AS customer_name,
COALESCE(SUM(oi.quantity), 0) AS total_units
FROM customers AS c
LEFT JOIN orders AS o
ON c.id = o.customer_id
LEFT JOIN order_items AS oi
ON o.id = oi.order_id
GROUP BY
c.id,
c.name
ORDER BY total_units DESC;Fungsi COALESCE() mengganti hasil NULL dengan nilai pengganti, dalam contoh ini 0. Jadi, pelanggan yang belum memiliki detail pesanan dapat ditampilkan dengan jumlah unit nol.
Namun, selalu periksa tingkat detail data yang sedang dihitung. Ketika tabel memiliki hubungan satu-ke-banyak, satu baris dari tabel utama bisa muncul berkali-kali dalam hasil JOIN.
12.2. Waspadai total yang terhitung berulang
Misalkan satu pesanan memiliki tiga baris detail barang. Jika kita menjumlahkan nilai yang berasal dari tabel orders setelah menggabungkannya dengan order_items, nilai pesanan tersebut bisa muncul tiga kali.
Hal yang sama dapat terjadi jika kita menggabungkan beberapa tabel yang masing-masing memiliki banyak baris terkait dengan entitas yang sama.
Untuk laporan keuangan, jangan langsung menjumlahkan nilai header transaksi setelah melakukan JOIN dengan detail tanpa memahami kardinalitas hubungan. Pastikan perhitungan dilakukan pada tingkat data yang tepat, atau agregasikan tabel detail terlebih dahulu.
13. Kesalahan Umum Saat Menggunakan SQL JOIN
Kesalahan 1: Tidak menuliskan kondisi ON yang benar
Contoh:
SELECT *
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.id;Query tersebut mungkin berjalan, tetapi kondisi hubungan yang digunakan salah untuk struktur contoh kita. customers.id harus dicocokkan dengan orders.customer_id, bukan orders.id.
Query yang benar:
SELECT *
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id;Selalu periksa kolom yang menjadi penghubung antartabel.
Kesalahan 2: Menggunakan SELECT * untuk semua tabel
Contoh:
SELECT *
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id;Query ini bisa menampilkan kolom id dari dua tabel, sehingga hasilnya lebih sulit dibaca.
Untuk laporan, pilih kolom yang memang dibutuhkan dan gunakan alias:
SELECT
c.id AS customer_id,
c.name AS customer_name,
o.id AS order_id,
o.order_date
FROM customers AS c
INNER JOIN orders AS o
ON c.id = o.customer_id;Kesalahan 3: Menganggap satu pelanggan selalu menghasilkan satu baris
Jika seorang pelanggan mempunyai lima pesanan, JOIN pelanggan dengan pesanan dapat menghasilkan lima baris untuk pelanggan tersebut.
Jangan menggunakan DISTINCT hanya untuk menghilangkan duplikasi yang terlihat tanpa memeriksa penyebabnya. Baris yang tampak berulang bisa jadi memang mewakili transaksi yang berbeda.
Kesalahan 4: Salah menempatkan filter pada LEFT JOIN
Kondisi WHERE yang memfilter kolom dari tabel kanan dapat menghilangkan baris yang tidak memiliki pasangan.
Jika semua baris tabel kiri harus tetap ditampilkan, pertimbangkan apakah kondisi tabel kanan sebaiknya ditempatkan di ON.
Kesalahan 5: Menggabungkan tabel dengan kondisi yang terlalu longgar
Jika kita menggabungkan dua tabel tanpa kondisi pencocokan yang tepat, hasilnya dapat menjadi Cartesian product: setiap baris dari tabel pertama dipasangkan dengan setiap baris dari tabel kedua.
Misalnya, tabel pertama memiliki 4 baris dan tabel kedua memiliki 5 baris. Jika semua kombinasi dihasilkan, hasilnya dapat berjumlah 20 baris.
Gunakan kondisi ON yang benar, kecuali jika memang sengaja membutuhkan seluruh kombinasi seperti pada analisis tertentu.
Kesalahan 6: Salah mengartikan NULL
NULL berarti nilai tidak tersedia atau tidak diketahui dalam konteks data, bukan angka nol atau teks kosong.
Untuk mencari nilai NULL, gunakan:
WHERE o.id IS NULL;Bukan:
WHERE o.id = NULL;14. Latihan SQL JOIN untuk Pemula
Sekarang waktunya mencoba sendiri. Gunakan empat tabel latihan TokoKita yang telah dijelaskan di atas.
{@body const [answers, setAnswers] = DIL.useState({})}
{@body const [checked, setChecked] = DIL.useState({})}
<box border radius="xl" padding={4} gap={4}>
<title size="lg">Latihan 1 — INNER JOIN</title> Tampilkan nama pelanggan dan nomor pesanan. Hanya pelanggan yang memiliki pesanan yang boleh muncul.
<text color="secondary" size="sm">Petunjuk: hubungkan customers dan orders.</text>
<textarea value={answers.q1 || ""} onChange={(v) => setAnswers((s) => ({...s, q1:v}))} placeholder="Tulis query SQL kamu di sini..." rows={4} />
<button block variant="outline" onClick={() => setChecked((s) => ({...s, q1:!s.q1}))}>{checked.q1 ? "Sembunyikan jawaban" : "Lihat jawaban"}</button>
{#if checked.q1} ```sql SELECT c.name, o.id AS order_id FROM customers AS c INNER JOIN orders AS o ON c.id = o.customer_id; ``` {/if} <divider />
<title size="lg">Latihan 2 — LEFT JOIN</title>
Tampilkan seluruh pelanggan, termasuk yang belum mempunyai pesanan. <textarea value={answers.q2 || ""} onChange={(v) => setAnswers((s) => ({...s, q2:v}))} placeholder="Tulis query SQL kamu di sini..." rows={4} />
<button block variant="outline" onClick={() => setChecked((s) => ({...s, q2:!s.q2}))}>{checked.q2 ? "Sembunyikan jawaban" : "Lihat jawaban"}</button>
{#if checked.q2} ```sql SELECT c.name, o.id AS order_id FROM customers AS c LEFT JOIN orders AS o ON c.id = o.customer_id; ``` {/if} <divider />
<title size="lg">Latihan 3 — Mencari pelanggan tanpa pesanan</title> Tampilkan nama pelanggan yang belum pernah melakukan transaksi.
<textarea value={answers.q3 || ""} onChange={(v) => setAnswers((s) => ({...s, q3:v}))} placeholder="Tulis query SQL kamu di sini..." rows={5} />
<button block variant="outline" onClick={() => setChecked((s) => ({...s, q3:!s.q3}))}>{checked.q3 ? "Sembunyikan jawaban" : "Lihat jawaban"}</button> {#if checked.q3} ```sql SELECT c.name FROM customers AS c LEFT JOIN orders AS o ON c.id = o.customer_id WHERE o.id IS NULL; ``` Hasilnya adalah Dewi. {/if} <divider />
<title size="lg">Latihan 4 — JOIN empat tabel</title> Tampilkan nama pelanggan, nomor pesanan, nama produk, dan jumlah barang yang dibeli.
<textarea value={answers.q4 || ""} onChange={(v) => setAnswers((s) => ({...s, q4:v}))} placeholder="Tulis query SQL kamu di sini..." rows={7} />
<button block variant="outline" onClick={() => setChecked((s) => ({...s, q4:!s.q4}))}>{checked.q4 ? "Sembunyikan jawaban" : "Lihat jawaban"}</button>
{#if checked.q4} ```sql SELECT c.name AS customer_name, o.id AS order_id, p.product_name, oi.quantity FROM customers AS c INNER JOIN orders AS o ON c.id = o.customer_id INNER JOIN order_items AS oi ON o.id = oi.order_id INNER JOIN products AS p ON oi.product_id = p.id; ``` {/if} </box> ## 15.
Kapan SQL JOIN Dibutuhkan dalam Dunia Kerja? SQL `JOIN` bukan hanya materi latihan. Kemampuan ini digunakan dalam banyak pekerjaan yang berhubungan dengan sistem informasi dan data.
- **Data Analyst:** menggabungkan data transaksi, pelanggan, produk, dan pembayaran untuk membuat laporan.
- **Data Scientist:** menyiapkan dataset dari beberapa sumber tabel sebelum melakukan analisis atau pemodelan.
- **Data Engineer:** membangun query transformasi data dan pipeline yang mengolah data dari berbagai tabel.
- **Software Engineer:** mengambil data yang dibutuhkan aplikasi, misalnya halaman riwayat pesanan dan detail transaksi.
- **System Analyst:** memahami hubungan antartabel untuk memetakan proses bisnis dan kebutuhan laporan.
Sebagai contoh, sebuah aplikasi e-commerce mungkin memiliki ratusan tabel. Ketika tim bisnis meminta laporan pelanggan, transaksi, dan pembayaran, kemampuan memahami relasi tabel akan membantu kita merancang query dengan benar. SQL JOIN adalah salah satu fondasi untuk membaca data relasional secara lebih utuh. ##
16. Ringkasan Materi | Materi | Fungsi |
|---|---| | `JOIN` / `INNER JOIN` | Mengambil baris yang memiliki pasangan sesuai kondisi penggabungan
| | `LEFT JOIN` | Mempertahankan semua baris tabel kiri
| | `ON` | Menentukan kondisi pencocokan antartabel
| | `WHERE` | Menyaring hasil berdasarkan kondisi | | Alias tabel | Memperpendek penulisan nama tabel
| | `IS NULL` | Memeriksa nilai NULL
| | `COUNT()` dan `SUM()` | Menghitung atau menjumlahkan data hasil penggabungan |
Jika kamu baru belajar SQL, fokuslah terlebih dahulu pada tiga hal:
a. Pahami relasi tabel, tuliskan kondisi `ON` yang benar, dan pastikan jenis `JOIN` sesuai dengan kebutuhan laporan.
b. Jangan terburu-buru menghafalkan semua jenis `JOIN`.
c. Mulai dari `INNER JOIN` dan `LEFT JOIN`, lalu tingkatkan latihan dengan menggabungkan tiga hingga empat tabel. ##
17. Lanjut Belajar SQL ke Tahap Berikutnya Setelah memahami cara menggabungkan tabel, kita sudah bisa membuat laporan yang lebih kompleks. Langkah berikutnya adalah mempelajari query yang lebih fleksibel untuk kebutuhan analisis dan pengolahan data. Pada artikel selanjutnya, kita akan membahas **Subquery, CASE, UNION, dan CTE**. Materi tersebut membantu kita membuat logika query yang lebih terstruktur, menyatukan hasil query, dan menyusun analisis secara bertahap. Jika kamu ingin mengulang materi sebelumnya, pelajari kembali:
1. **Artikel 01:** Belajar SQL untuk Pemula — Database, Tabel, dan `SELECT`.
2. **Artikel 02:** Belajar SQL CRUD — `INSERT`, `UPDATE`, dan `DELETE`.
3. **Artikel 03:** Belajar Fungsi Agregasi SQL — `COUNT`, `SUM`, `AVG`, `GROUP BY`, dan `HAVING`.
**Kesimpulan:** SQL JOIN membantu kita menghubungkan informasi yang disimpan dalam tabel berbeda menjadi satu hasil yang bermakna.
Ketika sudah memahami relasi tabel dan perbedaan `INNER JOIN` dengan `LEFT JOIN`, kamu akan lebih siap membangun query untuk kebutuhan aplikasi, laporan bisnis, dan analisis data.
--- ### Referensi resmi -
[MySQL 8.4 — JOIN Clause](https://dev.mysql.com/doc/refman/8.4/en/join.html) - [MySQL 8.4 — FOREIGN KEY Constraints (https://dev.mysql.com/doc/refman/8.4/en/create-table-foreign-keys.html)
Butuh solusi digital untuk bisnis Anda?
Diskusikan Proyek →