Topik ini membahas CROSS JOIN dan self-join, yaitu dua bentuk penggabungan yang tidak mencari pasangan antartabel. CROSS JOIN menghasilkan produk kartesius, yakni seluruh kombinasi baris dua tabel, sedangkan self-join menggabungkan satu tabel dengan dirinya sendiri untuk membaca hubungan antarbaris pada tabel yang sama. Dataset perpustakaan yang sama dipakai agar angka pada keluaran tetap saling menjelaskan dengan topik lain pada modul ini.
Produk kartesius#
CROSS JOIN memasangkan setiap baris tabel pertama dengan setiap baris tabel kedua tanpa kondisi apa pun, sehingga jumlah hasilnya selalu jumlah baris kiri dikali jumlah baris kanan. Tabel kedua tidak harus berbeda dari tabel pertama, sehingga kombinasi sesama anggota juga sah, tetapi contoh pertama memakai dua tabel yang berbeda agar hasilnya mudah dihitung. Jalankan query berikut untuk menghitung kombinasi seluruh anggota dengan seluruh buku.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT);
CREATE TABLE anggota (id INTEGER PRIMARY KEY, nama TEXT);
CREATE TABLE peminjaman (id INTEGER PRIMARY KEY, id_buku INTEGER, id_anggota INTEGER, tanggal_pinjam TEXT);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma'), (2, 'Peta Langit'), (3, 'Kode dan Sandi'),
(4, 'Sejarah Kertas'), (5, 'Jejak Angin'), (6, 'Arsip Suara');
INSERT INTO anggota VALUES
(1, 'Ali'), (2, 'Budi'), (3, 'Citra'),
(4, 'Dewi'), (5, 'Eka'), (6, 'Farhan');
INSERT INTO peminjaman VALUES
(1, 1, 1, '2026-03-02'), (2, 3, 2, '2026-03-04'),
(3, 1, 3, '2026-03-06'), (4, 99, 4, '2026-03-09'),
(5, 5, 5, '2026-03-11');
SELECT COUNT(*) FROM anggota CROSS JOIN buku;36Enam anggota dikali enam buku menghasilkan tiga puluh enam kombinasi. Pasangan seperti Ali dengan Jejak Angin tidak menyatakan peristiwa pinjam, melainkan kombinasi yang tersedia untuk dipilih lebih lanjut. Perkalian ini menjelaskan sifat hasilnya, karena setiap sel dari tabel perkalian enam kali enam terisi satu pasangan. Karena hasilnya membesar dengan cepat, CROSS JOIN hampir selalu diikuti penyaringan atau agregasi. Fungsi COUNT pada contoh di atas menghitung tanpa menampilkan pasangannya, sedangkan bagian berikut menampilkan kombinasi yang bermakna.
Kombinasi pasangan yang sah#
Kegunaan sah CROSS JOIN adalah menghasilkan seluruh kombinasi terlebih dahulu sebelum kombinasi tertentu dipilih, misalnya menyusun pasangan anggota untuk jadwal kelompok baca yang tidak memasangkan seseorang dengan dirinya sendiri. Jalankan query berikut yang menggabungkan tabel anggota dengan dirinya sendiri melalui dua alias (nama sementara), yaitu a1 dan a2.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT);
CREATE TABLE anggota (id INTEGER PRIMARY KEY, nama TEXT);
CREATE TABLE peminjaman (id INTEGER PRIMARY KEY, id_buku INTEGER, id_anggota INTEGER, tanggal_pinjam TEXT);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma'), (2, 'Peta Langit'), (3, 'Kode dan Sandi'),
(4, 'Sejarah Kertas'), (5, 'Jejak Angin'), (6, 'Arsip Suara');
INSERT INTO anggota VALUES
(1, 'Ali'), (2, 'Budi'), (3, 'Citra'),
(4, 'Dewi'), (5, 'Eka'), (6, 'Farhan');
INSERT INTO peminjaman VALUES
(1, 1, 1, '2026-03-02'), (2, 3, 2, '2026-03-04'),
(3, 1, 3, '2026-03-06'), (4, 99, 4, '2026-03-09'),
(5, 5, 5, '2026-03-11');
SELECT a1.nama, a2.nama
FROM anggota a1 CROSS JOIN anggota a2
WHERE a1.id < a2.id
ORDER BY a1.id, a2.id;Ali|Budi
Ali|Citra
Ali|Dewi
Ali|Eka
Ali|Farhan
Budi|Citra
Budi|Dewi
Budi|Eka
Budi|Farhan
Citra|Dewi
Citra|Eka
Citra|Farhan
Dewi|Eka
Dewi|Farhan
Eka|FarhanKeluaran memuat lima belas pasangan dari tiga puluh enam kombinasi awal. Syarat a1.id < a2.id membuang enam pasangan seorang anggota dengan dirinya sendiri, kemudian menyisakan satu arah untuk setiap pasangan dari tiga puluh kombinasi yang tersisa. Setiap nama muncul tepat lima kali dengan lima lawan yang berbeda, dan tidak ada pasangan yang tampil dua kali. Bentuk < dipilih daripada <> agar setiap pasangan hanya punya satu urutan, sehingga hasilnya bebas duplikat.
INNER JOIN tanpa ON#
Kesalahan yang paling sering terjadi pada join adalah menulis JOIN tanpa ON. SQLite tidak menolaknya, melainkan memperlakukan gabungan tanpa kendala itu sebagai CROSS JOIN. Jalankan query berikut yang memasangkan buku dengan anggota tanpa kondisi.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT);
CREATE TABLE anggota (id INTEGER PRIMARY KEY, nama TEXT);
CREATE TABLE peminjaman (id INTEGER PRIMARY KEY, id_buku INTEGER, id_anggota INTEGER, tanggal_pinjam TEXT);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma'), (2, 'Peta Langit'), (3, 'Kode dan Sandi'),
(4, 'Sejarah Kertas'), (5, 'Jejak Angin'), (6, 'Arsip Suara');
INSERT INTO anggota VALUES
(1, 'Ali'), (2, 'Budi'), (3, 'Citra'),
(4, 'Dewi'), (5, 'Eka'), (6, 'Farhan');
INSERT INTO peminjaman VALUES
(1, 1, 1, '2026-03-02'), (2, 3, 2, '2026-03-04'),
(3, 1, 3, '2026-03-06'), (4, 99, 4, '2026-03-09'),
(5, 5, 5, '2026-03-11');
SELECT COUNT(*) FROM buku JOIN anggota;
SELECT judul, nama FROM buku JOIN anggota
ORDER BY buku.id, anggota.id
LIMIT 3;36
Dasar Algoritma|Ali
Dasar Algoritma|Budi
Dasar Algoritma|CitraQuery pertama menghasilkan tiga puluh enam, persis seperti CROSS JOIN, karena tanpa ON tidak ada syarat yang membatasi pasangan. Tiga baris pada query kedua memperlihatkan akibatnya, yaitu judul buku yang dipasangkan dengan nama anggota secara tidak bermakna. Query semacam ini biasanya keliru secara logika tetapi tetap dijalankan tanpa pesan error, sehingga kesalahannya baru ketahuan ketika jumlah hasilnya jauh lebih besar dari dugaan.
Self-join pada tabel hierarkis#
Self-join menggabungkan satu tabel dengan dirinya sendiri, dan kegunaan utamanya adalah membaca hubungan yang tersimpan antarbaris tabel itu, misalnya hierarki kategori. Tambahkan tabel kategori berikut yang setiap barisnya merujuk kategori induknya melalui kolom id_induk, kemudian gabungkan tabel itu dengan dirinya sendiri.
CREATE TABLE kategori (
id INTEGER PRIMARY KEY,
nama TEXT,
id_induk INTEGER
);
INSERT INTO kategori VALUES
(1, 'Fiksi', NULL),
(2, 'Nonfiksi', NULL),
(3, 'Sains', 2),
(4, 'Sejarah', 2),
(5, 'Fisika', 3),
(6, 'Biologi', 3);
SELECT k.id, k.nama AS kategori, i.nama AS induk
FROM kategori k
LEFT JOIN kategori i ON i.id = k.id_induk
ORDER BY k.id;1|Fiksi|
2|Nonfiksi|
3|Sains|Nonfiksi
4|Sejarah|Nonfiksi
5|Fisika|Sains
6|Biologi|SainsKolom kategori berasal dari alias k, sedangkan kolom induk berasal dari alias i yang menunjuk tabel kategori yang sama, sehingga satu tabel bermain dua peran sekaligus. Sains tampil dengan induk Nonfiksi karena id_induknya 2, dan Fisika tampil dengan induk Sains karena id_induknya 3. Fiksi dan Nonfiksi menampilkan kolom induk yang kosong karena id_induknya NULL, dan LEFT JOIN dipilih justru agar dua kategori puncak itu tetap tampil. Tabel kategori enam baris ini mudah diperiksa dengan mata, sedangkan hierarki yang lebih dalam tetap dijawab dengan pola yang sama.
Peran alias pada self-join#
Alias pada self-join bukan hiasan, melainkan penanda peran yang wajib, karena dua salinan tabel yang sama tidak dapat dibedakan tanpa nama. Amati perbedaannya apabila hanya pasangan yang benar-benar memiliki induk yang diambil menggunakan INNER JOIN.
CREATE TABLE kategori (id INTEGER PRIMARY KEY, nama TEXT, id_induk INTEGER);
INSERT INTO kategori VALUES
(1, 'Fiksi', NULL), (2, 'Nonfiksi', NULL), (3, 'Sains', 2),
(4, 'Sejarah', 2), (5, 'Fisika', 3), (6, 'Biologi', 3);
SELECT k.nama AS kategori, i.nama AS induk
FROM kategori k
INNER JOIN kategori i ON i.id = k.id_induk
ORDER BY k.id;Sains|Nonfiksi
Sejarah|Nonfiksi
Fisika|Sains
Biologi|SainsVersi INNER JOIN hanya memuat empat kategori yang memiliki induk, sedangkan Fiksi dan Nonfiksi gugur karena NULL pada id_induk tidak memenuhi kondisi ON. Jenis join yang dipilih menentukan apakah baris tanpa induk ikut tampil dengan kolom kosong atau tersaring. Untuk hierarki tiga tingkat, pola yang sama diteruskan dengan menambahkan satu alias peran untuk setiap tingkat tambahan.
Ringkasan#
- CROSS JOIN menghasilkan seluruh kombinasi baris dua tabel tanpa kondisi, dengan jumlah hasil jumlah baris kiri dikali jumlah baris kanan.
- INNER JOIN tanpa ON diperlakukan sebagai CROSS JOIN, sehingga hasil membesar tanpa pesan error.
- Self-join membutuhkan alias peran agar dua salinan tabel yang sama dapat dibedakan.
- Jenis join menentukan nasib baris tanpa induk, yaitu ikut tampil dengan kolom
NULLpada LEFT JOIN atau tersaring pada INNER JOIN.
Referensi#
- SELECT — Dokumentasi SQLite — Bentuk CROSS JOIN, alias tabel, dan perlakuan gabungan tanpa kendala pada FROM.