Topik ini menutup modul join dengan rantai empat tabel sekaligus, yaitu pola yang muncul setiap kali laporan menghubungkan fakta dari beberapa tabel sekaligus. Fokusnya bukan sintaks baru, melainkan keterbacaan, urutan berpikir, dan kendali atas jumlah baris ketika rantainya panjang.
Blok penyiapan dataset#
# siapkan ulang tabel dan data contoh untuk topik ini
PGOPTIONS='-c client_min_messages=warning' psql -q -U postgres -d perpustakaan <<'SQL'
DROP TABLE IF EXISTS peminjaman, buku, anggota, kategori CASCADE;
CREATE TABLE kategori (id SERIAL PRIMARY KEY, nama TEXT NOT NULL UNIQUE);
CREATE TABLE anggota (id SERIAL PRIMARY KEY, nama TEXT NOT NULL, email TEXT UNIQUE, bergabung DATE NOT NULL, aktif BOOLEAN NOT NULL DEFAULT TRUE);
CREATE TABLE buku (id SERIAL PRIMARY KEY, judul TEXT NOT NULL, penulis TEXT NOT NULL, tahun INTEGER NOT NULL, kategori_id INTEGER REFERENCES kategori(id));
CREATE TABLE peminjaman (id SERIAL PRIMARY KEY, anggota_id INTEGER NOT NULL REFERENCES anggota(id), buku_id INTEGER NOT NULL REFERENCES buku(id), tanggal_pinjam DATE NOT NULL, tanggal_kembali DATE);
INSERT INTO kategori (nama) VALUES ('Pemrograman'), ('Sains'), ('Sejarah'), ('Fiksi'), ('Statistika');
INSERT INTO anggota (nama, email, bergabung, aktif) VALUES ('Ali Rahman', '[email protected]', '2024-01-15', TRUE), ('Budi Santoso', '[email protected]', '2024-03-02', TRUE), ('Citra Kirana', '[email protected]', '2024-05-20', FALSE), ('Dewi Lestari', '[email protected]', '2024-08-11', TRUE), ('Eka Pratama', NULL, '2025-01-30', TRUE);
INSERT INTO buku (judul, penulis, tahun, kategori_id) VALUES ('Dasar Basis Data', 'Sari Wulandari', 2021, 1), ('Jaringan Komputer', 'Ahmad Fauzi', 2019, 1), ('Fisika untuk Pemula', 'Rina Marlina', 2020, 2), ('Kimia Organik', 'Rina Marlina', 2022, 2), ('Sejarah Nusantara', 'Bambang Wijaya', 2018, 3), ('Cerita Kota Lama', 'Nur Aisyah', 2023, 4), ('Statistika Terapan', 'Sari Wulandari', 2022, 5), ('Algoritma dan Struktur Data', 'Ahmad Fauzi', 2021, 1);
INSERT INTO peminjaman (anggota_id, buku_id, tanggal_pinjam, tanggal_kembali) VALUES (1, 1, '2025-03-01', '2025-03-15'), (1, 7, '2025-03-05', '2025-03-20'), (2, 3, '2025-03-10', NULL), (3, 5, '2025-02-20', '2025-03-01'), (2, 1, '2025-04-02', NULL), (4, 6, '2025-04-07', NULL), (5, 8, '2025-04-09', '2025-04-25'), (4, 2, '2025-05-01', NULL);
SQLRantai empat tabel#
Laporan peminjaman yang bermakna menyebut peminjamnya, judul bukunya, dan kategorinya, sehingga empat tabel tergabung dalam satu query. Urutan penulisannya mengikuti jalur rujukan, yaitu memulai dari tabel fakta peminjaman lalu menjangkau satu per satu tabel penjelasnya.
# laporan peminjaman lengkap dari empat tabel
psql -U postgres -d perpustakaan -c "SELECT p.id, a.nama AS anggota, b.judul, k.nama AS kategori FROM peminjaman p JOIN anggota a ON p.anggota_id = a.id JOIN buku b ON p.buku_id = b.id JOIN kategori k ON b.kategori_id = k.id WHERE p.tanggal_kembali IS NULL ORDER BY p.id;" id | anggota | judul | kategori
----+--------------+---------------------+-------------
3 | Budi Santoso | Fisika untuk Pemula | Sains
5 | Budi Santoso | Dasar Basis Data | Pemrograman
6 | Dewi Lestari | Cerita Kota Lama | Fiksi
8 | Dewi Lestari | Jaringan Komputer | Pemrograman
(4 rows)Empat alias satu huruf menjaga setiap baris syarat tetap pendek, dan setiap JOIN berdiri sendiri dengan syarat ON yang menyebut kolom kedua tabelnya. Jumlah baris hasil tetap delapan, karena setiap peminjaman menemukan tepat satu anggota, satu buku, dan satu kategori.
Cara membaca dan menulis rantai panjang#
Keterbacaan rantai panjang ditopang tiga kebiasaan. Pertama, alias yang konsisten per tabel dideklarasikan sekali dan dipakai di seluruh query, termasuk pada WHERE dan ORDER BY. Kedua, setiap JOIN dan ON ditulis pada barisnya sendiri, sehingga menambah atau menghapus satu tabel berarti menambah satu pasang baris tanpa menyentuh yang lain. Ketiga, daftar kolom hasil menyebut asal setiap kolomnya, termasuk alias AS untuk kolom yang namanya berubah makna, seperti k.nama yang menjadi kategori.
Urutan penggabungan yang ditulis tidak mengubah hasil akhir untuk INNER JOIN, karena penggabungan bersifat asosiatif, dan perencana bebas menyusun urutan eksekusi yang paling murah. Urutan penulisan justru melayani manusia, yaitu dibaca sebagai alur cerita dari tabel fakta menuju tabel penjelasnya.
Menambah tabel dari dua arah#
Rantai nyata kadang bercabang, misalnya laporan yang sekaligus menyebut kategori buku dan jumlah peminjaman lain oleh anggota yang sama. Percabangan ditambahkan sebagai JOIN tambahan pada rantai, dengan syarat ON yang merujuk tabel yang sudah ada di dalam FROM.
Apabila satu sisi percabangan berpotensi tanpa pasangan, jenis join-nya ditentukan per sisi, yaitu LEFT JOIN untuk sisi yang harus tetap tampil. Kendali ini per tabel, bukan per query, sehingga satu rantai boleh mencampur INNER dan LEFT dengan sengaja, dan maksud tiap sisi terbaca dari jenis join-nya.
Kesalahan umum#
Kesalahan pertama adalah satu syarat ON yang terlupa ketika rantainya panjang, yang mengubah satu sisi rantai menjadi produk kartesian dan jumlah barisnya melonjak tak terkendali. Penangkalnya memeriksa jumlah baris hasil terhadap tabel fakta setiap kali satu tabel ditambahkan. Kesalahan kedua adalah menyebut kolom tanpa awalan ketika nama itu ada di beberapa tabel, misalnya nama yang dimiliki anggota, buku, dan kategori, sehingga server menolak dengan pesan kolom ambigu.
Kesalahan ketiga adalah mengira urutan JOIN menentukan performa. Perencana menyusun ulang urutan penggabungan berdasarkan statistik, dan upaya penalaan yang lebih berarti ditempatkan pada index kolom join, sebagaimana dibahas pada modul index dan performa.
Satu alat keterbacaan untuk rantai panjang adalah tabel turunan, yaitu subquery yang ditulis langsung pada FROM dan mempersingkat sebagian rantai menjadi satu langkah. Bentuk yang lebih formalnya adalah CTE pada modul subquery dan CTE. Penyisipannya tepat ketika satu bagian rantai memiliki makna sendiri, misalnya ringkasan per anggota yang kemudian dijoin, karena query yang memakainya terbaca sebagai dua gagasan yang bergabung, bukan enam tabel yang berantai tanpa jeda.
Ringkasan#
- Rantai multi-tabel dimulai dari tabel fakta dan menjangkau tabel penjelas satu per satu dengan JOIN dan ON tersendiri.
- Alias konsisten, satu pasang JOIN ON per baris, dan daftar kolom berawalan menjaga query panjang tetap terbaca.
- Urutan penulisan melayani keterbacaan, sedangkan urutan eksekusi ditentukan perencana berdasarkan statistik.
- Jenis join dipilih per sisi rantai, dengan LEFT JOIN untuk sisi yang barisnya wajib tetap tampil meski tanpa pasangan.
Referensi#
- Joined Tables — PostgreSQL Documentation — Referensi penggabungan beberapa tabel dalam satu FROM.
- Joins Between Tables — PostgreSQL Documentation — Bagian tutorial resmi tentang join.
- Controlling Plan Display — PostgreSQL Documentation — Pengantar cara perencana menyusun urutan eksekusi join.