Menggabungkan Query SQL dengan UNION & UNION ALL di SQL Server

Foto oleh Markus Winkler via Pexels

Menggabungkan Query dengan UNION dan UNION ALL di SQL Server

Halo teman-teman Malam Ngoding!

Pernahkah Anda dihadapkan pada situasi di mana Anda perlu mengambil data dari dua tabel atau lebih yang berbeda, namun ingin menampilkannya dalam satu set hasil tunggal? Mungkin Anda memiliki data penjualan dari kuartal yang berbeda, daftar karyawan dari dua departemen yang memiliki struktur data serupa, atau bahkan laporan transaksi dari berbagai sistem yang perlu digabungkan menjadi satu kesatuan. Di sinilah operator UNION dan UNION ALL di SQL Server memainkan peran krusial.

Berbeda dengan JOIN yang menggabungkan kolom dari tabel-tabel berdasarkan relasi antar kolom, UNION dan UNION ALL dirancang untuk menggabungkan baris hasil dari beberapa pernyataan SELECT yang terpisah. Ini sangat berguna ketika struktur kolom dari hasil query tersebut identik atau setidaknya kompatibel, namun sumber datanya berasal dari tempat yang berbeda. Mari kita selami lebih dalam kapan dan bagaimana menggunakan kedua operator ini secara efektif.

Mengapa Kita Membutuhkan UNION dan UNION ALL?

Dalam pengembangan aplikasi, seringkali data tidak disimpan dalam satu tabel tunggal secara homogen. Bayangkan sebuah sistem logistik yang mencatat pergerakan barang. Mungkin ada tabel terpisah untuk PengirimanDomestik dan PengirimanInternasional. Keduanya memiliki kolom seperti NomorResi, TanggalPengiriman, Status, dan NamaPenerima. Jika Anda ingin melihat semua pengiriman tanpa peduli asalnya, UNION adalah solusinya.

Masalah yang diselesaikan oleh UNION dan UNION ALL adalah kemampuan untuk mengonsolidasikan data dari sumber-sumber yang berbeda, tetapi dengan skema hasil yang serupa, menjadi satu tampilan logis. Ini mengurangi kebutuhan untuk menjalankan banyak query terpisah dan kemudian menggabungkannya di lapisan aplikasi, yang seringkali kurang efisien dan lebih sulit dikelola.

Perbedaan Mendasar: UNION vs. UNION ALL

Ini adalah inti dari pembahasan kita. Sekilas, keduanya tampak sama, namun ada perbedaan fundamental yang memiliki dampak signifikan pada hasil query maupun performa.

UNION: Menggabungkan dan Menghapus Duplikasi

Operator UNION berfungsi untuk menggabungkan hasil dari dua atau lebih query SELECT dan secara otomatis menghapus baris duplikat dari set hasil akhir. Artinya, jika ada satu baris data yang persis sama di semua kolom yang Anda pilih dari kedua query, UNION hanya akan menampilkan baris tersebut satu kali. Proses penghapusan duplikat ini memerlukan semacam proses sorting dan perbandingan, yang dapat berdampak pada performa, terutama pada set data yang sangat besar.

UNION ALL: Menggabungkan Tanpa Menghapus Duplikasi

Sebaliknya, operator UNION ALL juga menggabungkan hasil dari dua atau lebih query SELECT, namun tidak menghapus baris duplikat. Semua baris dari setiap query akan disertakan dalam hasil akhir, bahkan jika ada baris yang identik di antara query-query tersebut. Karena tidak ada proses deduplikasi yang perlu dilakukan, UNION ALL umumnya jauh lebih cepat dan lebih efisien dalam hal performa dibandingkan UNION.

Aturan Penting dalam Menggunakan UNION dan UNION ALL

Setup Tabel dan Data Demo untuk Ilustrasi UNION/UNION ALL

CREATE TABLE ProdukLaris_Q1 ( ID INT PRIMARY KEY, NamaProduk VARCHAR(100), Kategori VARCHAR(50), PenjualanUnit INT ); CREATE TABLE ProdukLaris_Q2 ( ID INT PRIMARY KEY, NamaProduk VARCHAR(100), Kategori VARCHAR(50), PenjualanUnit INT ); INSERT INTO ProdukLaris_Q1 (ID, NamaProduk, Kategori, PenjualanUnit) VALUES (1, 'Laptop X', 'Elektronik', 150), (2, 'Mouse Y', 'Aksesoris', 200), (3, 'Keyboard Z', 'Aksesoris', 180); INSERT INTO ProdukLaris_Q2 (ID, NamaProduk, Kategori, PenjualanUnit) VALUES (4, 'Smartphone A', 'Elektronik', 120), (5, 'Mouse Y', 'Aksesoris', 200), -- Deliberate duplicate row (NamaProduk, Kategori, PenjualanUnit) (6, 'Monitor B', 'Elektronik', 90);

Untuk memastikan query Anda berjalan dengan sukses, ada beberapa aturan yang wajib Anda patuhi:

  1. Jumlah Kolom yang Sama: Setiap pernyataan SELECT dalam konstruksi UNION atau UNION ALL harus memiliki jumlah kolom yang sama. Jika query pertama memilih 3 kolom, maka query kedua dan seterusnya juga harus memilih 3 kolom.
  2. Tipe Data yang Kompatibel: Tipe data dari kolom-kolom yang sesuai di setiap query harus kompatibel atau setidaknya dapat dikonversi secara implisit (misalnya, INT dan DECIMAL, atau VARCHAR dan NVARCHAR). Jika tidak, SQL Server akan menghasilkan error.
  3. Nama Kolom Hasil: Nama kolom dalam set hasil akhir akan ditentukan oleh nama kolom dari query SELECT pertama. Kolom dari query-query berikutnya akan diabaikan penamaannya.
  4. ORDER BY: Klausa ORDER BY hanya dapat diterapkan sekali, dan itu harus diletakkan di akhir query UNION atau UNION ALL secara keseluruhan. Ini akan mengurutkan seluruh set hasil yang sudah digabungkan.

Contoh Implementasi UNION dan UNION ALL

Menggunakan UNION ALL untuk Menggabungkan Semua Data (Termasuk Duplikat)

SELECT NamaProduk, Kategori, PenjualanUnit FROM ProdukLaris_Q1 UNION ALL SELECT NamaProduk, Kategori, PenjualanUnit FROM ProdukLaris_Q2;

Mari kita lihat contoh praktis menggunakan tabel penjualan. Misalkan kita memiliki data penjualan produk dari kuartal pertama dan kuartal kedua, yang beberapa di antaranya mungkin merupakan produk yang sama dengan jumlah penjualan yang sama.

Pertama, kita siapkan tabel dan data demonya:

Sekarang, mari kita lihat bagaimana UNION dan UNION ALL bekerja.

Contoh 1: Menggunakan UNION ALL (dengan Duplikasi)

Jika kita ingin melihat semua catatan penjualan dari kedua kuartal, termasuk jika ada produk yang muncul di kedua kuartal dengan detail penjualan yang sama persis, kita gunakan UNION ALL.

Perhatikan bahwa baris ('Mouse Y', 'Aksesoris', 200) muncul dua kali, karena baris tersebut ada di kedua tabel (dari sudut pandang kolom yang diseleksi). UNION ALL tidak peduli dengan duplikasi.

Contoh 2: Menggunakan UNION (Tanpa Duplikasi)

Jika kita hanya tertarik pada daftar unik produk yang laris (berdasarkan kombinasi Nama Produk, Kategori, dan Penjualan Unit) dari kedua kuartal, kita gunakan UNION.

Hasilnya akan menghilangkan salah satu baris ('Mouse Y', 'Aksesoris', 200) karena dianggap duplikat dari keseluruhan set hasil.

Contoh 3: Menggunakan UNION ALL dengan ORDER BY

Untuk mengurutkan seluruh hasil gabungan, klausa ORDER BY diletakkan di akhir.

ORDER BY diterapkan pada seluruh set hasil gabungan, mengurutkannya berdasarkan NamaProduk.

Contoh 4: Mengatasi Masalah Nama Kolom yang Berbeda

Meskipun Anda harus memastikan jumlah dan tipe data kolom kompatibel, nama kolom bisa berbeda di query individual. Namun, nama kolom hasil akan mengikuti query pertama. Ini adalah poin penting yang sering disalahpahami oleh developer pemula.

Misalkan ProdukLaris_Q1 memiliki kolom UnitTerjual dan ProdukLaris_Q2 memiliki kolom JumlahPenjualan. Keduanya bertipe INT. Anda bisa menggunakan UNION, tetapi nama kolom di hasil akan mengikuti query pertama.

Outputnya akan menggunakan nama kolom PenjualanUnit dari query pertama.

Kapan Sebaiknya Menggunakan UNION dan UNION ALL? (Trade-off)

Memilih antara UNION dan UNION ALL bukan sekadar preferensi, melainkan keputusan yang berdampak pada performa dan akurasi data.

  • Gunakan UNION ALL ketika:
    • Anda yakin tidak ada duplikasi yang relevan di antara set hasil, atau duplikasi tersebut tidak masalah dan justru perlu dipertahankan (misalnya, semua transaksi penjualan yang memang unik secara ID transaksi, tetapi produknya bisa sama).
    • Performa adalah prioritas utama. Karena UNION ALL tidak perlu melakukan operasi deduplikasi, ia jauh lebih cepat, terutama pada set data yang besar.
    • Anda ingin melakukan operasi agregat (seperti yang sudah kita bahas pada artikel Fungsi Agregat COUNT SUM AVG MIN MAX) pada semua baris, termasuk duplikat yang mungkin muncul dari sumber yang berbeda.
  • Gunakan UNION ketika:
    • Anda secara spesifik membutuhkan daftar item yang unik dari beberapa sumber (misalnya, daftar pelanggan unik dari berbagai kanal pemasaran, daftar produk unik di seluruh gudang).
    • Anda tahu bahwa duplikasi mungkin ada dan secara logis tidak diinginkan dalam hasil akhir.
    • Anda bersedia menerima potensi overhead performa yang timbul dari proses deduplikasi.

Kesalahan Umum yang Sering Dilakukan Developer Pemula

Menggunakan UNION untuk Menggabungkan Data Unik (Menghilangkan Duplikat)

SELECT NamaProduk, Kategori, PenjualanUnit FROM ProdukLaris_Q1 UNION SELECT NamaProduk, Kategori, PenjualanUnit FROM ProdukLaris_Q2;

Beberapa jebakan yang sering ditemui developer junior saat menggunakan UNION dan UNION ALL:

  1. Jumlah Kolom atau Tipe Data yang Tidak Sesuai: Ini adalah kesalahan paling dasar. Developer sering lupa atau salah menghitung jumlah kolom, atau mengabaikan tipe data yang tidak kompatibel, sehingga menyebabkan error.
  2. Mencoba Menggunakan WHERE atau ORDER BY di Tengah Query: Klausa-klausa ini harus diterapkan pada masing-masing SELECT (jika untuk filtering sebelum gabung) atau pada seluruh hasil UNION/UNION ALL (jika untuk pengurutan akhir). Mengaplikasikannya di tempat yang salah akan menyebabkan sintaks error.
  3. Selalu Menggunakan UNION secara Default: Banyak developer baru menggunakan UNION karena mereka ingin data unik, tanpa mempertimbangkan biaya performa. Dalam banyak skenario, UNION ALL sudah cukup dan jauh lebih cepat jika duplikasi yang ada tidak mengganggu logika bisnis atau sudah dijamin unik oleh kunci primer/logika lain di level sumber data.
  4. Menggabungkan Data yang Seharusnya Di-JOIN: Terkadang, developer mencoba menggunakan UNION untuk menggabungkan data yang secara relasional terkait dan seharusnya di-JOIN. Ingat, JOIN menggabungkan kolom, UNION menggabungkan baris. Memahami perbedaan fundamental ini sangat penting.
  5. Mengabaikan Potensi Duplikasi Bisnis di UNION ALL: Meskipun UNION ALL tidak menghapus duplikasi secara teknis, Anda perlu memastikan bahwa duplikasi tersebut secara logis diterima oleh bisnis. Misalnya, jika Anda menggabungkan daftar pelanggan dari dua sistem yang berbeda, dan seorang pelanggan terdaftar di keduanya, UNION ALL akan menampilkan dua entri. Apakah ini yang diinginkan? Jika tidak, maka UNION mungkin lebih tepat, atau Anda perlu filter lebih lanjut di salah satu query sebelum digabung.

Dampak pada Performa dan Keamanan

Menggabungkan dengan UNION ALL dan Mengurutkan Hasil Akhir

SELECT NamaProduk, Kategori, PenjualanUnit FROM ProdukLaris_Q1 UNION ALL SELECT NamaProduk, Kategori, PenjualanUnit FROM ProdukLaris_Q2 ORDER BY NamaProduk;

Performa

Seperti yang sudah disinggung, performa adalah pertimbangan utama. UNION memerlukan langkah tambahan untuk mendeteksi dan menghapus duplikat. Ini biasanya melibatkan pengurutan (sorting) data yang digabungkan atau penggunaan hash table. Untuk set data kecil, perbedaannya mungkin tidak terasa. Namun, pada sistem dengan jutaan baris data, perbedaan performa antara UNION dan UNION ALL bisa sangat signifikan.

Penggunaan indeks yang tepat pada kolom-kolom yang diseleksi di setiap query SELECT yang membentuk UNION/UNION ALL masih sangat relevan untuk mempercepat pengambilan data awal. Namun, operasi deduplikasi oleh UNION akan tetap menjadi bottleneck tersendiri.

Keamanan

Dari segi keamanan, operator UNION dan UNION ALL sendiri tidak secara inheren memperkenalkan kerentanan baru. Kerentanan umum seperti SQL Injection tetap menjadi perhatian pada setiap query SELECT yang Anda gunakan, baik itu digabung atau tidak. Developer harus memastikan bahwa semua input pengguna divalidasi dan diparameterisasi dengan benar untuk mencegah serangan. Ketika menggabungkan data dari berbagai sumber, pastikan juga bahwa penggabungan tersebut tidak secara tidak sengaja mengekspos data sensitif yang seharusnya terisolasi.

Kesimpulan

UNION dan UNION ALL adalah alat yang sangat powerful di tangan seorang developer SQL. Kemampuan untuk mengonsolidasikan set hasil dari beberapa query memberikan fleksibilitas luar biasa dalam pelaporan, analisis, dan integrasi data. Pemahaman yang kuat tentang perbedaan mereka — terutama terkait penanganan duplikasi dan dampaknya terhadap performa — adalah kunci untuk menulis query yang efisien dan akurat.

Selalu pertimbangkan tujuan akhir Anda: apakah Anda membutuhkan semua baris secara mentah, atau hanya baris yang unik? Pilihan yang tepat antara UNION dan UNION ALL akan menghemat waktu eksekusi query dan memastikan integritas data yang Anda sajikan. Setelah Anda mahir dalam menggabungkan query, langkah selanjutnya dalam mengelola data kompleks adalah memahami Subquery dan Penggunaannya dalam Query Kompleks, yang akan kita bahas di artikel berikutnya.

Frequently Asked Questions (FAQ)

Contoh Penanganan Perbedaan Nama Kolom di Query Pertama

SELECT NamaProduk, Kategori, PenjualanUnit FROM ProdukLaris_Q1 UNION ALL SELECT NamaProduk, Kategori, PenjualanUnit AS JumlahPenjualanAlias FROM ProdukLaris_Q2;

1. Bisakah saya menggunakan UNION atau UNION ALL dengan lebih dari dua query?

Ya, Anda bisa menggabungkan lebih dari dua query. Cukup tambahkan operator UNION atau UNION ALL di antara setiap pernyataan SELECT tambahan. Contoh: SELECT ... FROM TableA UNION SELECT ... FROM TableB UNION ALL SELECT ... FROM TableC;

2. Apa yang terjadi jika tipe data kolom tidak persis sama tetapi kompatibel?

SQL Server akan mencoba melakukan konversi tipe data implisit. Misalnya, jika satu kolom bertipe INT dan yang lain BIGINT, SQL Server biasanya akan mengonversi yang lebih kecil ke tipe data yang lebih besar. Namun, jika konversi tidak mungkin (misalnya, mencoba mengonversi string non-numerik ke integer), maka query akan gagal dengan error.

3. Apakah urutan query dalam UNION/UNION ALL memengaruhi hasil?

Urutan query memengaruhi nama kolom yang akan ditampilkan di hasil akhir (sesuai query pertama), tetapi tidak memengaruhi baris data yang digabungkan, kecuali jika Anda menggunakan ORDER BY di setiap sub-query (yang jarang dilakukan dan tidak disarankan untuk pengurutan hasil akhir).

Catatan dari Penulis

Menurut saya, memahami perbedaan fundamental antara <code>UNION</code> dan <code>UNION ALL</code> ini adalah salah satu 'aha moment' bagi banyak developer junior, termasuk saya dulu. Seringkali, kita hanya pakai <code>UNION</code> secara otomatis karena ingin 'data unik', tanpa menyadari overhead performa yang datang dengan operasi deduplikasi. Dari pengalaman saya, di banyak kasus, <code>UNION ALL</code> sebenarnya lebih dari cukup dan jauh lebih efisien, terutama saat kita sudah tahu data sumber kita tidak memiliki duplikasi yang relevan atau kita memang ingin melihat setiap record. Ini adalah contoh klasik di mana sedikit pemahaman lebih dalam tentang bagaimana sebuah operator bekerja di balik layar bisa memiliki dampak besar pada skalabilitas aplikasi.

Seri Belajar SQL Server:

← Sebelumnya: Fungsi Agregat COUNT SUM AVG MIN MAX

→ Selanjutnya: Subquery dan Penggunaannya dalam Query Kompleks