Foto oleh panumas nikhomkhai via Pexels

UNION dan UNION ALL dipakai untuk menggabungkan hasil dari dua atau lebih query SELECT menjadi satu hasil tunggal, berbeda dengan JOIN yang menggabungkan table secara horizontal berdasarkan kolom yang berelasi. UNION justru menggabungkan secara vertikal, menumpuk baris dari beberapa query menjadi satu daftar hasil.

Artikel ini membahas perbedaan keduanya dan kapan masing-masing cocok dipakai, termasuk dampak performa yang sering diabaikan ketika memilih UNION dibanding UNION ALL.

Syarat Menggunakan UNION

Agar UNION bisa dipakai, setiap query SELECT yang digabungkan harus memiliki jumlah kolom yang sama dan tipe data yang kompatibel pada posisi kolom yang bersesuaian.

Menggabungkan dua table berbeda jenis entitas

SELECT FullName, 'Customer' AS Sumber FROM Customers UNION SELECT SupplierName, 'Supplier' AS Sumber FROM Suppliers; -- Expected: satu daftar gabungan nama customer dan supplier, -- dengan kolom Sumber menandai asal masing-masing baris

UNION Menghapus Duplikat, UNION ALL Tidak

Perbedaan utama UNION vs UNION ALL

-- UNION: menghapus baris duplikat, perlu proses sorting tambahan SELECT City FROM Customers UNION SELECT City FROM Suppliers; -- UNION ALL: menyertakan semua baris apa adanya, lebih cepat SELECT City FROM Customers UNION ALL SELECT City FROM Suppliers; -- Expected: jika 'Jakarta' muncul di kedua table, -- UNION hanya menampilkan sekali, UNION ALL menampilkan dua kali

Karena UNION harus memeriksa dan menghapus duplikat, operasi ini lebih berat dibanding UNION ALL. Jika memang tidak masalah ada data duplikat atau sudah yakin tidak ada duplikat, UNION ALL selalu lebih disarankan demi performa.

Mengurutkan Hasil Gabungan

ORDER BY hanya boleh ditulis sekali, di akhir query terakhir

SELECT FullName FROM Customers UNION ALL SELECT SupplierName FROM Suppliers ORDER BY FullName; -- Expected: ORDER BY hanya boleh ditulis SEKALI, -- diterapkan ke seluruh hasil gabungan, bukan per query

Nama Kolom Hasil Mengikuti Query Pertama

Alias kolom ditentukan oleh query pertama dalam UNION

SELECT FullName AS Nama FROM Customers UNION ALL SELECT SupplierName FROM Suppliers; -- Expected: nama kolom hasil akhir adalah 'Nama', -- mengikuti alias dari query PERTAMA, meski SupplierName tidak diberi alias

Mengurutkan Hasil UNION dengan ORDER BY

ORDER BY diterapkan setelah UNION selesai digabung

SELECT ProductName, 'Aktif' AS Sumber FROM ActiveProducts UNION SELECT ProductName, 'Arsip' AS Sumber FROM ArchivedProducts ORDER BY ProductName; -- Expected: hasil gabungan dari kedua tabel, -- diurutkan berdasarkan ProductName secara alfabetis

ORDER BY pada query yang menggunakan UNION hanya boleh ditulis satu kali di akhir, setelah seluruh SELECT digabungkan, dan ia berlaku untuk keseluruhan hasil gabungan tersebut, bukan untuk masing-masing SELECT secara terpisah. Mencoba menambahkan ORDER BY di tengah, sebelum UNION kedua, akan menyebabkan error sintaks.

Kolom yang dipakai di ORDER BY harus merujuk ke nama kolom hasil akhir, bukan nama kolom asli dari salah satu tabel sumber jika namanya berbeda antara SELECT pertama dan kedua. Jika kedua SELECT memberi alias kolom yang berbeda, gunakan alias dari SELECT pertama karena itulah yang menentukan nama kolom pada hasil gabungan.

Perbedaan penting lainnya antara UNION dan UNION ALL adalah performa: karena UNION harus memeriksa dan membuang baris duplikat, ia memerlukan langkah pengurutan atau hashing tambahan di belakang layar, sehingga lebih lambat dibanding UNION ALL pada dataset yang besar. Jika sudah yakin tidak akan ada duplikat di antara dua hasil SELECT, atau duplikat memang diinginkan, UNION ALL adalah pilihan yang lebih efisien.

Aturan Kompatibilitas Kolom pada UNION dan Perbedaan Performa dengan UNION ALL

UNION menghapus duplikat, UNION ALL mempertahankan seluruh baris

-- Menggabungkan data pelanggan aktif dan arsip pelanggan lama SELECT CustomerID, CustomerName, 'Aktif' AS Status FROM Customers UNION SELECT CustomerID, CustomerName, 'Arsip' AS Status FROM CustomersArchive; -- UNION menghapus baris yang persis sama di kedua hasil -- UNION ALL mempertahankan semua baris termasuk duplikat SELECT ProductID FROM OrdersJanuari UNION ALL SELECT ProductID FROM OrdersFebruari;

Agar dua atau lebih query bisa digabung dengan UNION atau UNION ALL, setiap query harus menghasilkan jumlah kolom yang sama persis, dan tipe data pada posisi kolom yang sejajar harus kompatibel satu sama lain; nama kolom yang ditampilkan pada hasil akhir mengikuti nama kolom dari query yang pertama ditulis, meski query berikutnya memakai nama alias yang berbeda.

Perbedaan mendasar antara UNION dan UNION ALL adalah UNION secara otomatis menghapus baris duplikat dari hasil gabungan, proses yang secara internal memerlukan langkah pengurutan atau hashing tambahan untuk mendeteksi baris yang identik, sedangkan UNION ALL hanya menumpuk seluruh baris dari setiap query tanpa pemeriksaan duplikat sama sekali, sehingga jauh lebih ringan secara komputasi.

Karena perbedaan performa tersebut, UNION ALL sebaiknya selalu menjadi pilihan default kecuali memang ada kebutuhan bisnis yang jelas untuk menghilangkan duplikat, misalnya saat menggabungkan dua sumber data yang secara desain memang tidak mungkin saling tumpang tindih; memakai UNION padahal data sudah pasti unik hanya akan membebani server dengan pekerjaan penghapusan duplikat yang sebenarnya tidak diperlukan.

INTERSECT dan EXCEPT sebagai Alternatif UNION

INTERSECT dan EXCEPT untuk operasi himpunan selain UNION

-- INTERSECT: hanya baris yang muncul di KEDUA hasil query SELECT PelangganID FROM dbo.PelangganAktifBulanIni INTERSECT SELECT PelangganID FROM dbo.PelangganAktifBulanLalu; -- Hasil: pelanggan yang aktif di bulan ini DAN bulan lalu -- EXCEPT: baris dari query pertama yang TIDAK ADA di query kedua SELECT PelangganID FROM dbo.PelangganAktifBulanLalu EXCEPT SELECT PelangganID FROM dbo.PelangganAktifBulanIni; -- Hasil: pelanggan yang aktif bulan lalu tapi berhenti bulan ini (churn)

Selain UNION dan UNION ALL yang menggabungkan hasil dua query, SQL Server juga menyediakan operator himpunan INTERSECT dan EXCEPT yang masing-masing meniru operasi irisan dan selisih pada teori himpunan matematika. INTERSECT mengembalikan hanya baris yang muncul pada kedua hasil query secara bersamaan, sementara EXCEPT mengembalikan baris dari query pertama yang tidak ditemukan pada hasil query kedua, dengan urutan query sangat menentukan hasil akhir EXCEPT karena operasinya tidak simetris.

Ketiga operator himpunan ini, UNION, INTERSECT, dan EXCEPT, memiliki aturan yang sama soal kompatibilitas kolom: jumlah kolom pada kedua query harus sama dan tipe datanya harus kompatibel, serta nama kolom akhir mengikuti query pertama. Secara default, ketiganya juga menghilangkan baris duplikat dari hasil akhirnya, berbeda dari UNION ALL yang sengaja mempertahankan duplikat demi performa yang lebih cepat.

Kasus penggunaan paling umum untuk EXCEPT adalah mendeteksi data yang hilang atau churn, seperti mencari pelanggan yang aktif bulan lalu namun tidak lagi aktif bulan ini, sementara INTERSECT sering dipakai untuk audit konsistensi data antara dua sumber, misalnya memastikan daftar ID produk pada sistem gudang sama persis dengan daftar ID produk pada sistem penjualan. Sebelum SQL Server mendukung kedua operator ini sejak versi 2008, developer harus menyimulasikannya memakai kombinasi LEFT JOIN dan IS NULL yang jauh lebih rumit dan rawan kesalahan.

ORDER BY yang Berlaku untuk Keseluruhan Hasil UNION

ORDER BY tunggal di akhir UNION

-- ORDER BY pada UNION hanya boleh ditulis SEKALI di akhir, -- berlaku untuk gabungan hasil kedua query SELECT CustomerName, 'Aktif' AS Status, TotalBelanja FROM dbo.Customers UNION ALL SELECT CustomerName, 'Arsip' AS Status, TotalBelanja FROM dbo.CustomersArchive ORDER BY TotalBelanja DESC; -- Expected: baris dari kedua table tercampur, -- diurutkan bersama berdasarkan TotalBelanja tanpa peduli asal table

Ketika beberapa query digabungkan dengan UNION atau UNION ALL, klausa ORDER BY hanya boleh dituliskan satu kali di bagian paling akhir setelah seluruh query, dan urutan tersebut berlaku untuk keseluruhan hasil gabungan, bukan untuk masing-masing query secara terpisah. Menulis ORDER BY pada query pertama sebelum UNION akan menghasilkan error sintaks, karena SQL Server menganggap seluruh rangkaian UNION sebagai satu unit hasil tunggal yang hanya diurutkan di akhir.

Kolom yang dipakai pada ORDER BY setelah UNION harus merujuk ke nama kolom atau alias dari query pertama, karena itulah nama kolom yang dipakai pada hasil akhir gabungan. Memahami aturan ini penting ketika menggabungkan data dari dua table dengan struktur mirip namun nama kolom berbeda, karena pengurutan akhir tetap mengikuti nama kolom hasil UNION, bukan nama kolom asli dari table kedua yang digabungkan.

Kesalahan Umum yang Sering Terjadi

Memakai UNION padahal UNION ALL sudah cukup

Jika sudah yakin tidak ada data duplikat antar query atau duplikat memang diharapkan, memakai UNION tetap memaksa SQL Server melakukan proses pengecekan duplikat yang sebenarnya tidak diperlukan, membuang resource komputasi secara percuma.

Menulis ORDER BY di setiap query sebelum UNION

ORDER BY pada query individual sebelum UNION tidak akan memengaruhi urutan hasil akhir (dan pada beberapa kasus menyebabkan error sintaks), karena ORDER BY hanya valid ditulis sekali di akhir keseluruhan UNION.

Kapan Pendekatan Ini Tidak Cocok Dipakai

UNION ALL lebih cepat namun bisa menghasilkan data duplikat yang tidak diinginkan jika sumber datanya memang tumpang tindih. Pastikan memahami karakteristik data sebelum memilih UNION ALL demi performa, karena data duplikat yang lolos ke laporan akhir bisa menyebabkan angka yang digandakan secara keliru.

Ringkasan

UNION dan UNION ALL berguna saat perlu menggabungkan hasil dari beberapa sumber data yang memiliki struktur kolom serupa. Pilih UNION ALL sebagai default kecuali memang ada kebutuhan eksplisit untuk menghilangkan duplikat.

Seri Belajar SQL Server:

← Sebelumnya: Fungsi Agregat COUNT SUM AVG MIN MAX

→ Selanjutnya: Subquery dan Penggunaannya dalam Query Kompleks