LEFT JOIN mempertahankan sisi kiri; kelanjutan logikanya mudah kita duga — RIGHT JOIN mempertahankan sisi kanan. Jenis join ini jarang menjadi bintang utama: setiap query RIGHT JOIN selalu bisa ditulis ulang sebagai LEFT JOIN dengan posisi tabel dibalik, dan banyak tim basis data justru mewajibkan penulisan ulang tersebut. Meski begitu, kita tetap perlu membacanya dengan benar, karena query RIGHT JOIN akan terus kita temui di kode lama, di hasil generate tool, maupun di dokumentasi pihak ketiga. Pada chapter ini kita membuktikan perilaku RIGHT JOIN di atas pasangan tabel pelanggan dan pesanan, melihat mengapa foreign key membuat salah satu arahnya terlihat identik dengan INNER JOIN, lalu menuliskan versi LEFT JOIN yang hasilnya persis sama.
Menyiapkan Pasangan Tabel Latihan #
Data latihan tetap pasangan yang sama dengan dua chapter sebelumnya. Ingat sebarannya, karena dua arah RIGHT JOIN yang akan kita uji menghasilkan kelakuan yang berbeda justru karena sebaran ini: pesanan hanya dimiliki empat pelanggan, sementara tiga pelanggan tidak memiliki pesanan:
DROP DATABASE IF EXISTS belajar_join;
CREATE DATABASE belajar_join;
USE belajar_join;
CREATE TABLE pelanggan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(50) NOT NULL,
kota VARCHAR(30) NOT NULL
);
CREATE TABLE pesanan (
id INT AUTO_INCREMENT PRIMARY KEY,
pelanggan_id INT NOT NULL,
tanggal DATE NOT NULL,
total DECIMAL(12,2) NOT NULL,
FOREIGN KEY (pelanggan_id) REFERENCES pelanggan(id)
);
INSERT INTO pelanggan (nama, kota) VALUES
('Budi Santoso', 'Jakarta'),
('Siti Rahayu', 'Bandung'),
('Andi Wijaya', 'Surabaya'),
('Rina Melati', 'Yogyakarta'),
('Dewi Lestari', 'Bandung'),
('Tono Hartono', 'Medan'),
('Sari Puspita', 'Jakarta');
INSERT INTO pesanan (pelanggan_id, tanggal, total) VALUES
(1, '2026-01-05', 170000.00),
(2, '2026-01-07', 50000.00),
(1, '2026-01-10', 62000.00),
(1, '2026-01-12', 15000.00),
(3, '2026-01-15', 137000.00),
(2, '2026-01-18', 85000.00),
(4, '2026-01-08', 125000.00);Output yang Dihasilkan:
Query OK, 0 rows affected, 1 warning (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Database changed
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 7 rows affected (0.00 sec)
Records: 7 Duplicates: 0 Warnings: 0
Query OK, 7 rows affected (0.00 sec)
Records: 7 Duplicates: 0 Warnings: 0Semua Baris Sisi Kanan Tampil #
Pada RIGHT JOIN, tabel yang ditulis setelah kata RIGHT JOIN adalah sisi yang dipertahankan. Query pertama menempatkan pesanan di posisi tersebut:
SELECT pn.id AS pesanan_id, pn.total, p.nama
FROM pelanggan p
RIGHT JOIN pesanan pn ON p.id = pn.pelanggan_id
ORDER BY pn.id;Output yang Dihasilkan:
+------------+-----------+--------------+
| pesanan_id | total | nama |
+------------+-----------+--------------+
| 1 | 170000.00 | Budi Santoso |
| 2 | 50000.00 | Siti Rahayu |
| 3 | 62000.00 | Budi Santoso |
| 4 | 15000.00 | Budi Santoso |
| 5 | 137000.00 | Andi Wijaya |
| 6 | 85000.00 | Siti Rahayu |
| 7 | 125000.00 | Rina Melati |
+------------+-----------+--------------+
7 rows in set (0.00 sec)Hasilnya tujuh baris dan tidak ada satu pun NULL — setiap pesanan selalu punya nama pelanggan. Ini bukan kebetulan, melainkan konsekuensi langsung dari desain relasi kita: kolom pelanggan_id dideklarasikan NOT NULL dan dijaga foreign key, sehingga setiap baris pesanan pasti menemukan pasangan pelanggannya. Ketika tabel anak dipertahankan di join terhadap induknya, seluruh baris anak pasti berpasangan dan RIGHT JOIN menghasilkan baris yang sama dengan INNER JOIN. Baris NULL hanya mungkin muncul bila ada baris kanan yang pasangannya absen — misalnya pesanan tanpa pelanggan, yang justru mustahil terjadi di skema yang benar.
Membalik Posisi: NULL Muncul di Sisi Kiri #
Gambaran berubah total ketika pelanggan yang diposisikan sebagai sisi kanan. Perhatikan bahwa klausa FROM kini menulis pesanan lebih dulu:
SELECT p.nama, pn.id AS pesanan_id, pn.total
FROM pesanan pn
RIGHT JOIN pelanggan p ON p.id = pn.pelanggan_id
ORDER BY p.id, pn.id;Output yang Dihasilkan:
+--------------+------------+-----------+
| nama | pesanan_id | total |
+--------------+------------+-----------+
| Budi Santoso | 1 | 170000.00 |
| Budi Santoso | 3 | 62000.00 |
| Budi Santoso | 4 | 15000.00 |
| Siti Rahayu | 2 | 50000.00 |
| Siti Rahayu | 6 | 85000.00 |
| Andi Wijaya | 5 | 137000.00 |
| Rina Melati | 7 | 125000.00 |
| Dewi Lestari | NULL | NULL |
| Tono Hartono | NULL | NULL |
| Sari Puspita | NULL | NULL |
+--------------+------------+-----------+
10 rows in set (0.00 sec)Hasilnya sepuluh baris — persis keluaran LEFT JOIN pada chapter sebelumnya. Mekanismenya simetris: MySQL memproses setiap baris pelanggan (kini sisi kanan yang dipertahankan) dan mencari pasangannya di pesanan (kini sisi kiri). Budi, Siti, Andi, dan Rina menemukan pasangan sehingga menampilkan pesanan-pesanannya; Dewi, Tono, dan Sari tidak menemukan pasangan sehingga tetap tampil dengan kolom pesanan_id dan total bernilai NULL. Satu-satunya hal yang berbeda dari LEFT JOIN adalah posisi penulisan tabel, bukan isi hasilnya. Pelajaran praktisnya: membaca query RIGHT JOIN selalu dimulai dengan mengidentifikasi tabel mana yang ditulis setelah RIGHT JOIN, karena tabel itulah yang dijamin tampil utuh.
Menulis Ulang sebagai LEFT JOIN #
Karena setiap RIGHT JOIN memiliki padanan LEFT JOIN, kebiasaan industri menganjurkan satu gaya penulisan saja. Versi LEFT JOIN dari query terakhir: tukar posisi kedua tabel dan ganti kata kuncinya:
SELECT p.nama, pn.id AS pesanan_id, pn.total
FROM pelanggan p
LEFT JOIN pesanan pn ON p.id = pn.pelanggan_id
ORDER BY p.id, pn.id;Output yang Dihasilkan:
+--------------+------------+-----------+
| nama | pesanan_id | total |
+--------------+------------+-----------+
| Budi Santoso | 1 | 170000.00 |
| Budi Santoso | 3 | 62000.00 |
| Budi Santoso | 4 | 15000.00 |
| Siti Rahayu | 2 | 50000.00 |
| Siti Rahayu | 6 | 85000.00 |
| Andi Wijaya | 5 | 137000.00 |
| Rina Melati | 7 | 125000.00 |
| Dewi Lestari | NULL | NULL |
| Tono Hartono | NULL | NULL |
| Sari Puspita | NULL | NULL |
+--------------+------------+-----------+
10 rows in set (0.00 sec)Sepuluh baris yang sama persis: urutan baris, nilai NULL, hingga kolom hasil identik dengan versi RIGHT JOIN. Alasan kebiasaan ini bukan sekadar selera gaya. Pertama, konsistensi: bila seluruh tim hanya memakai LEFT JOIN, setiap pembaca query tidak perlu memikirkan ulang arah join — sisi yang dipertahankan selalu yang ditulis pertama. Kedua, portabilitas dan keterbacaan historis: beberapa database lawas dan sebagian tools SQL memiliki dukungan RIGHT JOIN yang lebih terbatas atau berperilaku berbeda, sedangkan LEFT JOIN hampir selalu menjadi fitur yang paling matang dan paling banyak dipakai orang. Praktik amannya: tulis RIGHT JOIN hanya bila menulis ulangnya justru membuat urutan tabel jadi tidak alami.
Membersihkan Database Latihan #
DROP DATABASE belajar_join;Output yang Dihasilkan:
Query OK, 2 rows affected (0.00 sec)Referensi #
RIGHT JOIN tuntas dibedah: sisi kanan dijamin tampil, sisi kiri diisi NULL bila pasangan absen, dan foreign key yang sehat membuat arah anak-ke-induk terlihat sama dengan INNER JOIN. Kita juga melihat bahwa setiap RIGHT JOIN dapat ditulis ulang sebagai LEFT JOIN terbalik tanpa mengubah hasil. Dua jenis join yang sudah kita kuasai sama-sama memasangkan baris lewat kondisi kesamaan kunci; chapter berikutnya membahas CROSS JOIN — join tanpa kondisi pencocokan yang menghasilkan semua kombinasi baris, lengkap dengan kegunaan dan bahayanya.