Self Join Hanyalah Join dengan Alias
Tidak ada yang istimewa dari self join. Self join adalah JOIN biasa yang kedua sisinya kebetulan tabel yang sama. Kuncinya, SQLite butuh cara untuk membedakan kedua salinan itu, jadi kamu memberi masing-masing sebuah alias.
Kamu memakainya setiap kali sebuah baris di tabel merujuk ke baris lain di tabel yang sama. Kasus klasiknya: tabel employees di mana setiap baris punya manager_id yang menunjuk ke karyawan lain:
Ada tidak punya manajer. Boris dan Cleo melapor ke Ada. Diego dan Esme melapor ke Boris. Hubungannya sepenuhnya ada di dalam satu tabel, dan justru di situlah self join sangat berguna.
Bentuk Dasarnya
Untuk memasangkan setiap karyawan dengan nama manajernya, join employees dengan dirinya sendiri. Satu salinan berperan sebagai "karyawan", salinan lainnya sebagai "manajer":
Baca sebagai dua tabel yang kebetulan berbagi penyimpanan. e adalah baris karyawan; m adalah baris manajer. Kondisi join e.manager_id = m.id menyejajarkan keduanya: untuk setiap karyawan, cari baris di m yang id-nya cocok dengan manager_id milik karyawan itu.
Perhatikan bahwa Ada tidak muncul. manager_id miliknya bernilai NULL, dan INNER JOIN membuang baris yang tidak punya pasangan.
Mempertahankan Baris Tanpa Pasangan: LEFT JOIN
Jika kamu ingin semua orang ada di hasil, termasuk yang tidak punya manajer, ganti dengan LEFT JOIN:
Sekarang Ada muncul dengan NULL di kolom manajer. Mekanisme self join-nya sama, hanya jenis join-nya yang melakukan apa yang selalu dilakukan LEFT JOIN: menyimpan setiap baris dari sisi kiri dan mengisi yang kosong jika tidak ada pasangannya.
Inilah bentuk yang biasanya kamu inginkan saat menampilkan daftar orang. "Tidak punya manajer" adalah informasi; membuang barisnya tidak.
Alias Itu Tidak Opsional
Coba join tanpa alias, dan SQLite tidak tahu apa maksudmu:
SELECT name, manager_id FROM employees JOIN employees ON manager_id = id;
-- Error: ambiguous column name: name
Setiap kolom muncul dua kali, sekali dari setiap salinan tabel, dan SQLite tidak bisa memilih. Alias menyelesaikan masalah ini dengan memberi setiap salinan namanya sendiri. Pilih alias yang menggambarkan peran baris itu, bukan nama tabelnya:
edanmuntuk karyawan/manajer.parentdanchilduntuk hierarki.adanbsaat kamu membandingkan pasangan sembarang.
Alias itulah satu-satunya alasan self join bisa terbaca dengan rapi.
Mencari Pasangan di Dalam Satu Tabel
Self join tidak hanya untuk hierarki. Setiap kali kamu ingin membandingkan baris di tabel yang sama, pola ini cocok. Ini daftar produk, dan kita ingin setiap pasangan yang harganya sama:
Ada dua hal yang perlu diperhatikan. Pertama, a.price = b.price adalah kondisi pencocokan yang sebenarnya. Kedua, a.id < b.id adalah yang mencegah query mengembalikan setiap pasangan dua kali (sekali sebagai (Mug, Notebook), sekali lagi sebagai (Notebook, Mug)) dan mencegah setiap baris dipasangkan dengan dirinya sendiri. Trik < itu layak diingat, karena muncul setiap kali kamu membuat daftar pasangan.
Naik Dua Level
Self join menangani satu lompatan dalam hierarki. Ingin tahu manajer dari manajer setiap karyawan? Join tiga kali:
Setiap alias baru mewakili satu level lagi ke atas pohon. Cara ini baik-baik saja untuk dua atau tiga lompatan, tapi cepat berantakan: kamu harus tahu kedalaman hierarkinya saat menulis query, dan menambahkan satu join untuk setiap level. Itulah tembok yang ingin ditembus oleh CTE rekursif.
Kapan Tidak Perlu Memakai Self Join
Self join adalah alat yang tepat saat kamu butuh kolom dari kedua sisi hubungan di hasilnya. Jika kamu hanya perlu memfilter, misalnya mencari setiap karyawan yang manajernya Ada, subquery sering lebih enak dibaca:
Tanpa akrobat alias, dan maksudnya tidak mungkin salah dipahami. Patokannya: apakah kamu ingin data dari kedua baris di output? Self join. Apakah kamu hanya butuh satu nilai untuk dibandingkan? Subquery.
Untuk hierarki dengan kedalaman sembarang (bagan organisasi, pohon file, komentar berutas), kedua pola ini tidak bisa diandalkan. Itu wilayah CTE rekursif.
Selanjutnya: Subquery
Self join dan subquery menyelesaikan masalah yang beririsan, dan mengetahui mana yang cocok akan menghemat banyak waktumu memelototi SQL nanti. Halaman berikutnya membahas subquery secara mendalam, yaitu bentuk skalar, berkorelasi, dan IN, serta di mana masing-masing unggul.
Pertanyaan yang sering diajukan
Apa itu self join di SQLite?
Self join adalah JOIN biasa di mana sebuah tabel di-join dengan dirinya sendiri. Kamu memberi tabel yang sama dua alias berbeda agar SQLite bisa memperlakukannya sebagai dua sumber baris yang terpisah, lalu mencocokkan baris berdasarkan kolom yang menghubungkan satu baris dengan baris lain, paling sering hubungan induk/anak seperti karyawan/manajer.
Kenapa self join butuh alias?
Tanpa alias, SQLite tidak bisa tahu salinan tabel mana yang kamu maksud saat kamu menulis nama kolom. Memberi setiap salinan aliasnya sendiri (misalnya e untuk karyawan dan m untuk manajer) membuatmu bisa menulis e.manager_id = m.id tanpa ambigu. Alias ini tidak opsional: query-nya tidak akan bisa di-parse tanpanya.
Kapan sebaiknya memakai self join dan kapan subquery?
Pakai self join jika kamu ingin kolom dari kedua baris muncul di hasil, misalnya nama karyawan dan nama manajernya di baris yang sama. Pakai subquery jika kamu hanya perlu memfilter atau mencari satu nilai. Untuk hierarki yang sangat dalam, keduanya tidak cocok; CTE rekursif adalah alat yang tepat.