INNER JOIN SQL: Cara Kerja + Contoh Kasus Penjualan
Blog/Tutorial SQL/INNER JOIN SQL: Cara Kerja + Contoh Kasus Penjualan

INNER JOIN SQL: Cara Kerja + Contoh Kasus Penjualan

BimaBima
·15 Februari 2026·10 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

TL;DR

INNER JOIN nggabungin dua tabel lewat kolom kunci yang sama, dan cuma nyisain baris yang ketemu pasangannya di kedua tabel. Baris yang gak punya pasangan langsung dibuang dari hasil, jadi jumlah baris hasil query bisa lebih sedikit dari tabel aslinya. Ini JOIN paling sering dipakai analis, biasanya buat nyambungin tabel transaksi ke tabel master produk atau pelanggan.

INNER JOIN nggabungin dua tabel lewat kolom kunci yang nilainya sama, dan cuma nyisain baris yang ketemu pasangannya di dua-duanya. Baris yang jomblo langsung dibuang dari hasil.

Ini JOIN yang paling sering kamu pakai sebagai analis. Tabel transaksi biasanya cuma nyimpen id_produk, bukan nama produknya. Nama produknya ada di tabel lain. INNER JOIN yang nyambungin dua-duanya.

Kalau kamu baru pertama kali ketemu JOIN, tenang. Query pertamanya cuma 4 baris.

Apa itu INNER JOIN di SQL?

INNER JOIN adalah operasi yang nyocokin baris dari dua tabel berdasarkan kolom kunci, terus nampilin baris yang cocok aja. Kalau satu baris di tabel kiri nggak nemu pasangan di tabel kanan, baris itu nggak muncul di hasil. Begitu juga sebaliknya.

Sintaks dasarnya:

SELECT kolom_yang_kamu_mau
FROM tabel_kiri
INNER JOIN tabel_kanan
  ON tabel_kiri.kunci = tabel_kanan.kunci;

Kata INNER boleh dihapus. JOIN doang artinya sama persis dengan INNER JOIN di semua database populer. Tapi aku saranin tetap ditulis biar niat kamu jelas kebaca orang lain.

Gimana cara kerja INNER JOIN?

Database ngecek tiap baris di tabel kiri, terus nyari baris di tabel kanan yang nilai kuncinya sama. Ketemu, dua baris itu digabung jadi satu baris panjang. Nggak ketemu, barisnya dilewatin.

Aku pakai data Toko Berkah buat contohnya. Dua tabel: produk (master) dan penjualan (transaksi).

CREATE TABLE produk (
  id_produk   INTEGER PRIMARY KEY,
  nama_produk TEXT,
  kategori    TEXT,
  harga       INTEGER
);

CREATE TABLE penjualan (
  id_penjualan INTEGER PRIMARY KEY,
  tanggal      TEXT,
  id_produk    INTEGER,
  qty          INTEGER
);

INSERT INTO produk VALUES
(1,'Beras Premium 5kg','Sembako', 68500),
(2,'Minyak Goreng 2L','Sembako', 34750),
(3,'Gula Pasir 1kg','Sembako', 16250),
(4,'Kopi Bubuk 200g','Minuman', 21375),
(5,'Teh Celup 25s','Minuman', 12000);

INSERT INTO penjualan VALUES
(101,'2026-02-10', 1, 3),
(102,'2026-02-10', 3, 12),
(103,'2026-02-11', 2, 7),
(104,'2026-02-11', 4, 9),
(105,'2026-02-12', 1, 2),
(106,'2026-02-12', 9, 4);

Perhatiin baris terakhir. Transaksi 106 nyatet id_produk = 9, padahal produk nomor 9 nggak ada di tabel produk. Data kotor kayak gini normal di sistem beneran, biasanya sisa produk yang udah dihapus.

Sekarang JOIN-nya:

SELECT p.tanggal, pr.nama_produk, p.qty, pr.harga
FROM penjualan p
INNER JOIN produk pr ON p.id_produk = pr.id_produk
ORDER BY p.tanggal;

Hasilnya:

tanggalnama_produkqtyharga
2026-02-10Beras Premium 5kg368.500
2026-02-10Gula Pasir 1kg1216.250
2026-02-11Minyak Goreng 2L734.750
2026-02-11Kopi Bubuk 200g921.375
2026-02-12Beras Premium 5kg268.500

Lima baris. Padahal tabel penjualan isinya enam. Transaksi 106 raib, soalnya id_produk = 9 nggak nemu pasangan.

Ini sifat INNER JOIN yang wajib kamu inget: dia diam-diam ngebuang baris. Nggak ada warning, nggak ada error. Kalau kamu nggak ngecek, omzet transaksi 106 hilang dari laporan.

Makanya biasain cek jumlah baris sebelum dan sesudah JOIN:

SELECT COUNT(*) FROM penjualan;                        -- 6

SELECT COUNT(*) FROM penjualan p
INNER JOIN produk pr ON p.id_produk = pr.id_produk;    -- 5

Beda satu. Itu sinyal buat kamu nyelidikin, bukan langsung lanjut bikin chart.

Contoh kasus: omzet per produk Toko Berkah

JOIN sendirian jarang jadi tujuan akhir. Biasanya dia langkah pertama sebelum diagregasi. Ini query yang paling sering aku tulis buat rekap toko:

SELECT pr.nama_produk,
       SUM(p.qty)            AS total_qty,
       SUM(p.qty * pr.harga) AS total_omzet
FROM penjualan p
INNER JOIN produk pr ON p.id_produk = pr.id_produk
GROUP BY pr.nama_produk
ORDER BY total_omzet DESC;

Hasilnya:

nama_produktotal_qtytotal_omzet
Beras Premium 5kg5342.500
Minyak Goreng 2L7243.250
Gula Pasir 1kg12195.000
Kopi Bubuk 200g9192.375

Ada temuan menarik di sini. Gula kejual 12 unit, jauh lebih laris dari beras yang cuma 5 unit. Tapi omzet beras hampir dua kali lipat omzet gula.

Kalau pemilik toko cuma lihat kolom qty, dia bakal nambahin stok gula dan ngurangin beras. Padahal yang nyumbang duit paling besar justru beras. Ini alasan kenapa JOIN penting: angka qty doang nggak cukup buat ambil keputusan.

Teh Celup nggak muncul sama sekali di hasil, soalnya nggak pernah kejual. INNER JOIN ngebuang produk yang nggak punya transaksi. Kalau kamu justru mau lihat produk yang belum laku, pakai LEFT JOIN.

Apa beda ON dan WHERE di INNER JOIN?

ON nentuin gimana dua tabel disambungin. WHERE nyaring hasilnya setelah nyambung. Di INNER JOIN, dua-duanya ngasih hasil sama, tapi bacanya beda.

-- Syarat penyambung di ON, filter di WHERE (rekomendasi)
SELECT pr.nama_produk, SUM(p.qty * pr.harga) AS omzet
FROM penjualan p
INNER JOIN produk pr ON p.id_produk = pr.id_produk
WHERE pr.kategori = 'Sembako'
GROUP BY pr.nama_produk;

Hasilnya cuma tiga produk sembako, total omzet Rp 780.750.

Kenapa kebiasaan ini penting? Soalnya di LEFT JOIN, naruh filter di ON atau WHERE bikin hasil yang beda jauh. Kalau kamu udah biasain dari INNER JOIN, kamu nggak bakal kejebak nanti.

Kesalahan umum pakai INNER JOIN

  • Nggak sadar baris hilang. INNER JOIN buang baris tanpa pasangan secara diam-diam. Selalu bandingin COUNT sebelum dan sesudah JOIN.
  • Hasil dobel gara-gara kunci nggak unik. Kalau id_produk muncul dua kali di tabel produk, tiap transaksi yang cocok bakal digandain. Omzet kamu tiba-tiba dua kali lipat. Cek keunikan kunci pakai SELECT id_produk, COUNT(*) FROM produk GROUP BY id_produk HAVING COUNT(*) > 1;
  • Lupa alias tabel. Kalau dua tabel punya kolom bernama sama, database bingung. Kasih alias pendek kayak p dan pr, terus tulis p.qty, bukan qty polos.
  • JOIN pakai kolom yang tipenya beda. Kolom id_produk bertipe TEXT di satu tabel dan INTEGER di tabel lain? Hasilnya kosong tanpa error. Samain tipenya dulu.
  • Kolom kunci ada spasi tersembunyi. Ini penyebab JOIN gagal yang paling nyebelin, soalnya nggak keliatan mata. Bersihin pakai TRIM dulu.

FAQ

Apa itu INNER JOIN di SQL?

INNER JOIN adalah cara nggabungin dua tabel lewat kolom kunci yang nilainya sama. Hasilnya cuma baris yang ketemu pasangannya di kedua tabel. Baris yang nggak punya pasangan langsung dibuang. Contoh paling umum: nyambungin tabel penjualan ke tabel produk lewat id_produk, biar kamu bisa lihat nama produk, bukan cuma angka id-nya.

Apa bedanya INNER JOIN dan LEFT JOIN?

INNER JOIN cuma nyisain baris yang punya pasangan di dua tabel. LEFT JOIN nyimpen semua baris dari tabel kiri, walau nggak ada pasangannya di tabel kanan, dan kolom kanannya diisi NULL. Pakai INNER JOIN kalau kamu cuma butuh data yang lengkap. Pakai LEFT JOIN kalau kamu justru mau nemuin yang nggak punya pasangan, misalnya produk yang belum pernah laku.

Kenapa hasil INNER JOIN barisnya jadi lebih banyak?

Soalnya kolom kunci di salah satu tabel nggak unik. Kalau satu id_produk muncul dua kali di tabel produk, tiap baris penjualan yang cocok bakal digandain jadi dua. Cek dulu keunikan kuncinya pakai COUNT dan GROUP BY sebelum JOIN. Kalau totalnya membengkak, hampir pasti masalahnya di sini, bukan di query JOIN-nya.

Apa beda ON dan WHERE di INNER JOIN?

ON nentuin gimana dua tabel disambungin, WHERE nyaring hasil setelah disambungin. Di INNER JOIN, naruh syarat di ON atau WHERE hasilnya sama. Tapi di LEFT JOIN hasilnya beda jauh, jadi biasain dari sekarang: syarat penyambung taruh di ON, syarat filter taruh di WHERE.

Apakah INNER JOIN bisa lebih dari dua tabel?

Bisa. Tinggal tumpuk INNER JOIN berikutnya di bawahnya, misalnya penjualan JOIN produk lalu JOIN kategori. Tiap JOIN butuh klausa ON sendiri. Tapi hati-hati, tiap tabel tambahan yang kuncinya nggak unik bisa gandain baris. Cek jumlah barisnya tiap kali kamu nambah satu JOIN baru.

Penutup

INNER JOIN itu pintu masuk ke hampir semua analisis serius. Tabel transaksi nyimpen id, tabel master nyimpen artinya, dan JOIN yang nyatuin.

Dua kebiasaan yang bakal nyelametin kamu: cek COUNT sebelum dan sesudah JOIN, dan pastiin kolom kuncinya unik di tabel master.

Sintaks lengkap INNER JOIN per database ada di halaman fungsi INNER JOIN, dan istilah kunci penyambungnya aku jelasin di glossary foreign key. Referensi resminya bisa kamu cek di dokumentasi JOIN PostgreSQL.

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