Join Menjahit Dua Tabel Menjadi Satu
Database relasional sengaja memecah data ke beberapa tabel: pelanggan di satu tabel, pesanan di tabel lain, produk di tabel ketiga. Dengan begitu, setiap fakta tersimpan di satu tempat saja. Tapi saat kamu ingin menjawab pertanyaan sungguhan ("pelanggan mana memesan apa?"), kamu perlu menyatukan kembali potongan-potongan itu. Itulah tugas join.
INNER JOIN adalah andalannya. Join ini memasangkan baris dari dua tabel setiap kali sebuah kondisi cocok, lalu membuang sisanya.
Ada tiga pelanggan dan tiga pesanan, tapi Chen tidak punya pesanan, jadi Chen tidak muncul. Itulah bagian "inner": hanya baris yang punya pasangan yang bertahan.
Model Berpikirnya: Pasangkan Baris, Lalu Filter
Bacalah INNER JOIN seperti ini: ambil setiap baris dari tabel pertama, lihat setiap baris dari tabel kedua, dan simpan pasangannya hanya jika kondisi ON bernilai benar. Secara konsep, ini adalah perkalian silang raksasa yang diikuti sebuah filter. SQLite sebenarnya tidak mengerjakannya seperti itu (SQLite memakai index jika bisa), tapi model ini tepat untuk menebak hasil yang keluar.
Beberapa kebiasaan yang layak kamu ambil di sini:
- Beri alias pada tabel (
customers AS c) jika kamu akan menyebutnya lebih dari sekali. Kodenya jadi lebih bersih. - Tulis nama kolom lengkap dengan tabelnya (
c.name,o.total) jika kolom itu bisa saja dimiliki kedua tabel. - Urutan dalam
ON o.customer_id = c.idtidak berpengaruh:c.id = o.customer_idbekerja sama persis.
INNER JOIN vs JOIN
Di SQLite (dan SQL standar), JOIN saja berarti INNER JOIN. Kata kunci INNER boleh tidak ditulis.
Kedua gaya menghasilkan rencana query dan baris yang sama. Menulis lengkap INNER JOIN sedikit membantu keterbacaan di kode yang mencampur beberapa jenis join, karena maksudnya jadi jelas di samping LEFT JOIN beberapa baris di bawahnya.
ON vs USING
Jika kolom join punya nama yang sama di kedua tabel, USING (column) lebih singkat daripada ON a.col = b.col:
USING (customer_id) melakukan dua hal: mencocokkan customer_id yang sama, dan menyatukan kolomnya sehingga hanya muncul sekali di hasil. Pakai ini jika kedua sisi memang memakai nama yang sama. Tetap pakai ON jika namanya berbeda (orders.customer_id = customers.id) atau kondisinya lebih dari satu persamaan.
Join Tiga Tabel
Sambung beberapa join dengan menambahkan klausa JOIN ... ON ... lagi. Masing-masing menghubungkan hasil sementara ke tabel lain.
Baca dari atas ke bawah: pelanggan terhubung ke pesanan, pesanan terhubung ke item. Setiap baris di output mewakili satu kombinasi pelanggan, pesanan, dan item. Apa pun yang tidak punya pasangan di titik mana pun sepanjang rantai itu akan dibuang. Itulah aturan inner join yang diterapkan di setiap langkah.
Memfilter dengan WHERE
ON menentukan cara memasangkan baris. WHERE memfilter hasil yang sudah dipasangkan. Khusus untuk inner join, menaruh kondisi tambahan di ON atau di WHERE menghasilkan baris yang sama, tapi konvensinya adalah menaruh kondisi join di ON dan filter baris di WHERE.
Query itu terbaca sebagai "join pelanggan dan pesanan, lalu simpan hanya pelanggan dari UK yang pesanannya di atas 20." Dua peran, dua klausa, dan dirimu di masa depan akan berterima kasih. (Begitu kamu mulai menulis LEFT JOIN, perbedaan ON/WHERE tidak lagi sekadar soal tampilan, tapi itu topik halaman berikutnya.)
Beberapa Kondisi di ON
ON bisa berisi ekspresi boolean apa pun, bukan hanya satu persamaan. Ini berguna jika relasinya melibatkan lebih dari satu kolom, atau jika kamu ingin memfilter sisi kanan saat join berlangsung.
Pesanan yang dibatalkan hilang karena kondisi keduanya gagal. Untuk inner join, kamu juga bisa menulis WHERE o.status = 'paid' dan mendapat hasil yang sama. Versi ON menjaga logika "apa yang dihitung sebagai pasangan" tetap dekat dengan join-nya.
Kesalahan yang Sering Terjadi
Beberapa hal yang sering bikin orang tersandung:
- Lupa menulis klausa
ON.FROM a INNER JOIN btanpaONadalah error sintaks di SQLite. (Koma saja, sepertiFROM a, b, memang bisa dijalankan, tapi hasilnya cross join, dan itu hampir tidak pernah yang kamu mau.) - Duplikat yang tidak terduga. Jika seorang pelanggan punya tiga pesanan, nama pelanggan itu muncul tiga kali di hasil. Itu perilaku join yang benar, bukan bug. Agregasikan dengan
GROUP BYjika kamu ingin satu baris per pelanggan. - Baris yang hilang. Jika seorang pelanggan seharusnya muncul tapi tidak ada, berarti kondisi join-nya tidak cocok. Periksa apakah ada
NULLdi kolom join, atau pakaiLEFT JOIN. - Nama kolom yang ambigu.
SELECT id FROM customers JOIN orders ON ...menghasilkan error karena kedua tabel punya kolomid. Tulis lengkap dengan tabelnya:c.idatauo.id.
Selanjutnya: LEFT JOIN
INNER JOIN sangat cocok jika tidak adanya pasangan berarti "lewati baris ini." Tapi terkadang kamu ingin semua pelanggan tercantum, termasuk yang belum punya pesanan, dengan NULL sebagai pengganti data yang tidak ada. Itulah LEFT JOIN, yang dibahas berikutnya.
Pertanyaan yang sering diajukan
Apa fungsi INNER JOIN di SQLite?
INNER JOIN mengembalikan baris yang punya pasangan di kedua tabel sesuai kondisi ON. Baris dari sisi mana pun yang tidak punya pasangan dibuang. Ini adalah jenis join bawaan: JOIN dan INNER JOIN artinya sama di SQLite.
Apa perbedaan INNER JOIN dan LEFT JOIN di SQLite?
INNER JOIN hanya menyimpan baris yang punya pasangan. LEFT JOIN menyimpan setiap baris dari tabel kiri dan mengisi sisi kanan dengan NULL jika tidak ada pasangannya. Pakai INNER JOIN jika tidak adanya pasangan berarti 'lewati baris ini', dan LEFT JOIN jika tidak adanya pasangan berarti 'tetap tampilkan'.
Bisakah INNER JOIN tiga tabel di SQLite?
Bisa. Tambahkan satu klausa JOIN ... ON ... lagi. Setiap join menghubungkan hasil sementara ke tabel baru. Tidak ada batas pasti, tapi keterbacaannya cepat menurun setelah empat atau lima tabel, dan di titik itu CTE sering membantu.
Kapan sebaiknya memakai USING dan bukan ON?
USING (column) adalah jalan pintas jika kolom join punya nama yang sama di kedua tabel. Penulisannya lebih ringkas dan menyatukan kolom yang dobel menjadi satu di output. Pakai ON setiap kali nama kolomnya berbeda atau kamu butuh kondisi yang lebih rumit.