MariaDB
 sql >> Teknologi Basis Data >  >> RDS >> MariaDB

Operator Kumpulan SQL MariaDB

Operator set adalah operator SQL yang menangani penggabungan, dengan cara yang berbeda, set hasil yang berbeda. Katakanlah Anda memiliki dua SELECT . yang berbeda s yang ingin Anda gabungkan menjadi satu set hasil, operator set ikut bermain. MariaDB telah mendukung UNION dan UNION ALL set operator untuk waktu yang lama, dan ini adalah operator set SQL yang paling umum.

Tapi kita lebih dulu di sini, izinkan saya menjelaskan operator set SQL yang kita miliki dan cara kerjanya. Jika Anda ingin mencobanya, Anda dapat menggunakan penerapan Server MariaDB yang ada, atau mencobanya di database awan MariaDB SkySQL.

UNION dan UNION SEMUA

UNION dan UNION ALL set operator menambahkan hasil dari dua atau lebih set hasil. Mari kita mulai dengan UNION ALL dan UNION kemudian akan menjadi variasi dari UNION ALL .

Mari kita lihat seperti apa di SQL. Mari kita asumsikan kita menjalankan toko web dan untuk produk yang kita jual, kita memiliki inventaris. Sekarang kita ingin melihat semua produk yang sedang dipesan atau ada dalam inventaris, kueri untuk ini akan terlihat seperti ini:

 PILIH oi.prod_id, p.prod_name FROM order_items oi GABUNG produk p ON oi.prod_id =p.id UNION SEMUA PILIH i.prod_id, p.prod_name FROM inventory i JOIN products p ON i.prod_id =p.id; 

Ini, dalam teori himpunan, adalah UNION dari set produk yang telah dipesan dan set produk yang ada di persediaan. Yang secara teori baik-baik saja, tetapi ada masalah dengan hasil kueri ini. Masalahnya adalah bahwa produk yang muncul di pesanan dan inventaris, atau di beberapa tempat di inventaris, akan muncul lebih dari satu kali di output. Masalah ini adalah mengapa UNION ALL tidak banyak digunakan dan sebagai gantinya UNION DISTINCT (DISTINCT adalah default dan dapat diabaikan) digunakan. Misalnya:

PILIH oi.prod_id, p.prod_name FROM order_items oi GABUNG produk p ON oi.prod_id =p.id UNION PILIH i.prod_id, p.prod_name FROM inventory i JOIN products p ON i.prod_id =p.id; 

Dengan kueri ini, produk yang sedang dipesan atau ada di inventaris hanya dicantumkan satu kali. Perhatikan bahwa ketika kami menghapus duplikat di sini, ini adalah nilai yang dibandingkan, sehingga dua baris dengan nilai yang sama di kolom yang sama dianggap sama, meskipun nilainya berasal dari tabel atau kolom yang berbeda.

Sejujurnya, tidak ada kueri di atas yang tidak dapat dilakukan dengan SELECT biasa dari produk tabel dan beberapa bergabung. Dalam beberapa hal UNION mungkin lebih mudah dibaca. Di sisi lain, jika kita ingin memiliki daftar produk yang dipesan atau di inventaris, dan juga ingin tahu yang mana, maka kuerinya akan seperti ini:

 SELECT 'On order', oi.prod_id, p.prod_name FROM order_items oi JOIN products p ON oi.prod_id =p.id UNION SELECT 'Inventory', i.prod_id, p.prod_name FROM inventory i JOIN products p ON i.prod_id =p.id;

Berikut adalah kueri yang tidak mudah dilakukan dengan SELECT sederhana dari produk tabel karena kita melihat baris yang sama dari tabel produk dua kali (sekali untuk order_items dan sekali untuk inventaris ).

Lebih banyak operator kumpulan SQL

Dengan MariaDB Server 10.3 datang dua operator set SQL baru, sebagian besar diperkenalkan untuk meningkatkan kompatibilitas Oracle, tetapi operator ini berguna dalam hak mereka sendiri. MariaDB Server 10.4 kemudian menambahkan kemampuan untuk mengontrol prioritas operator yang ditetapkan. Kami akan melihat itu juga. Tanpa kemampuan untuk mengontrol prioritas operator, operator yang ditetapkan tidak selalu berfungsi seperti yang Anda inginkan atau harapkan.

Operator set SQL yang baru adalah INTERSECT dan EXCEPT dan mereka berguna, terutama saat menggunakan analitik. Juga, meskipun JOIN s dan konstruksi lainnya sering dapat digunakan sebagai gantinya, operator set SQL memungkinkan sintaks SQL yang dapat lebih mudah dibaca dan dipahami. Dan, jika Anda memiliki aplikasi Oracle yang Anda migrasikan ke MariaDB, kegunaan operator ini jelas.

Operator set INTERSECT

INTERSECT operator akan mengembalikan semua item yang ada di dua atau lebih set, atau dalam istilah SQL, semua baris yang ada di dua set hasil. Dalam hal ini, penampang dari dua set item dibuat. Dalam istilah SQL itu berarti bahwa hanya baris yang ada di kedua set yang dikembalikan, jadi jika saya ingin memeriksa produk mana yang saya pesan dan yang juga ada dalam inventaris, kueri mungkin terlihat seperti ini:

 PILIH oi.prod_id, p.prod_name FROM order_items oi JOIN products p ON oi.prod_id =p.id INTERSECT SELECT i.prod_id, p.prod_name FROM inventory i JOIN products p ON i.prod_id =p.id; 

Sekali lagi, kueri ini dapat dibuat menggunakan JOIN pada produk tabel, tetapi kueri di atas sedikit lebih jelas tentang apa yang ingin kami capai.

Operator set KECUALI

Dalam kasus EXCEPT operator, kami menginginkan item yang ada di salah satu set, tetapi tidak di yang lain. Jadi, sekali lagi menggunakan contoh di atas, jika kita ingin melihat produk yang kita pesan tetapi tidak memiliki persediaan, kita bisa menulis query seperti ini:

 PILIH oi.prod_id, p.prod_name FROM order_items oi GABUNG produk p ON oi.prod_id =p.id KECUALI PILIH i.prod_id, p.prod_name FROM inventory i JOIN products p ON i.prod_id =p.id; 

Sekali lagi, ada cara lain untuk menulis kueri khusus ini, tetapi untuk kueri lain yang lebih canggih saat kita menggabungkan data dari dua tabel yang berbeda, hal ini tidak terjadi.

Menggabungkan beberapa set operator

Anda dapat menggabungkan lebih dari 2 set operator jika ini berguna. Misalnya, mari kita lihat apakah kita dapat menemukan produk yang sedang dipesan dan telah dikirim atau ada dalam persediaan. SQL untuk ini akan terlihat seperti ini:

PILIH oi.prod_id, p.prod_name FROM order_items oi JOIN products p ON oi.prod_id =p.id INTERSECT SELECT d.prod_id, p.prod_name FROM delivery d JOIN products p ON d.prod_id =p.id UNION SELECT i.prod_id, p.prod_name FROM inventory i JOIN products p ON i.prod_id =p.id;

Untuk mengungkapkan hal ini dalam bahasa sederhana, apa yang terjadi adalah pertama-tama saya memeriksa produk mana yang dipesan dan telah dikirim, lalu saya menggabungkan rangkaian produk ini dengan semua produk dalam inventaris. Produk apa pun yang tidak ada dalam kumpulan hasil tidak ada dalam inventaris tetapi mungkin sedang dipesan atau mungkin telah dikirimkan, tetapi tidak keduanya.

Tapi sekarang, mari kita ungkapkan ini secara berbeda, dan lihat apa yang terjadi. Saya ingin daftar semua produk yang tersedia atau telah dikirim dan sedang dipesan. SQL kemudian akan menjadi seperti ini, mirip dengan SQL di atas tetapi sedikit berbeda:

 PILIH i.prod_id, p.prod_name FROM inventory i JOIN products p ON i.prod_id =p.id UNION SELECT oi.prod_id, p.prod_name FROM order_items oi JOIN products p ON oi.prod_id =p.id INTERSECT SELECT d.prod_id, p.prod_name DARI pengiriman d GABUNG produk p ON d.prod_id =p.id;

Bagaimana Anda menafsirkan ini kemudian? Apakah Anda mencantumkan produk yang tersedia dan yang sedang dipesan dan produk yang sedang dikirim? Ini adalah apa yang terlihat seperti ini, kan? Hanya saja INTERSECT (dan EXCEPT dalam hal ini) memiliki diutamakan melalui UNION . Kedua pernyataan SQL menghasilkan kumpulan hasil yang sama, setidaknya di MariaDB dan beginilah cara Standar SQL mengatakan segala sesuatunya harus bekerja. Tapi ada pengecualian, Oracle.

Cara kerjanya di Oracle

Oracle telah memiliki keempat operator set SQL (UNION , UNION ALL , INTERSECT dan EXCEPT ) untuk waktu yang lama, jauh sebelum mereka distandarisasi, jadi implementasinya sedikit berbeda. Mari kita coba dengan tabel di atas dan masukkan beberapa data di dalamnya. Datanya sangat sederhana dan mencerminkan perusahaan yang tidak begitu sukses, tetapi ini berfungsi sebagai contoh, dan kami hanya menampilkan kolom yang relevan di sini.

Tabel produk order_items persediaan pengiriman
Kolom prod_id nama_prod id_pesanan prod_id prod_id prod_id
Data 1 Vas Biru 1 1 1 2
2 Vas Merah 2 1 2 3
3 Karpet Merah 2 3

Dengan data yang ada, mari kita lihat lagi pernyataan SQL terakhir di atas. Ada fitur yang memungkinkan Anda untuk mengontrol prioritas, dan itu adalah menggunakan tanda kurung, atau tanda kurung (Diperkenalkan di MariaDB 10.4, lihat https://jira.mariadb.org/browse/MDEV-11953), dan gunakan ini untuk mengilustrasikan apa yang terjadi, pernyataannya akan terlihat seperti ini:

 MariaDB> PILIH i.prod_id, p.prod_name -> FROM inventory i JOIN products p ON i.prod_id =p.id -> UNION -> (SELECT oi.prod_id, p.prod_name -> FROM order_items oi JOIN products p ON oi.prod_id =p.id -> INTERSECT -> SELECT d.prod_id, p.prod_name -> FROM pengiriman d GABUNG produk p PADA d.prod_id =p.id); +---------+------------+ | prod_id | nama_prod | +---------+------------+ | 1 | Vas Biru | | 2 | Vas Merah | | 3 | Karpet Merah | +---------+------------+ 3 baris dalam set (0,001 detik)

Sekarang, mari gunakan teknik yang sama untuk menerapkan tiga komponen kueri agar beroperasi dalam urutan yang ketat:

 MariaDB> (PILIH i.prod_id, p.prod_name -> FROM inventory i JOIN products p ON i.prod_id =p.id -> UNION -> SELECT oi.prod_id, p.prod_name -> FROM order_items oi JOIN products p ON oi.prod_id =p.id) -> INTERSECT -> SELECT d.prod_id, p.prod_name -> FROM pengiriman d GABUNG produk p ON d.prod_id =p.id; +---------+------------+ | prod_id | nama_prod | +---------+------------+ | 2 | Vas Merah | | 3 | Karpet Merah | +---------+------------+ 2 baris dalam set (0,001 detik)

Dan terakhir tanpa tanda kurung:

 MariaDB [test]> PILIH i.prod_id, p.prod_name -> FROM inventory i JOIN products p ON i.prod_id =p.id -> UNION -> SELECT oi.prod_id, p.prod_name -> FROM order_items oi GABUNG produk p ON oi.prod_id =p.id -> INTERSECT -> PILIH d.prod_id, p.prod_name -> FROM pengiriman d GABUNG produk p ON d.prod_id =p.id; +---------+------------+ | prod_id | nama_prod | +---------+------------+ | 1 | Vas Biru | | 2 | Vas Merah | | 3 | Karpet Merah | +---------+------------+ 3 baris dalam set (0,001 detik)

Kami melihat bahwa MariaDB, mengikuti standar, mengasumsikan bahwa INTERSECT didahulukan daripada UNION . Yang membawa kita ke Oracle. Mari kita coba SQL di atas di Oracle menggunakan sqlplus:

 SQL> PILIH i.prod_id, p.prod_name 2 FROM inventory i JOIN products p ON i.prod_id =p.id 3 UNION 4 SELECT oi.prod_id, p.prod_name 5 FROM order_items oi JOIN products p ON oi.prod_id =p.id 6 INTERSECT 7 PILIH d.prod_id, p.prod_name 8 DARI pengiriman d GABUNG produk p ON d.prod_id =p.id; PROD_ID PROD_NAME ---------- ------------------------------ 2 Vas Merah 3 Karpet Merah 

Apa yang terjadi di sini, Anda bertanya? Nah, Oracle tidak mengikuti standar. Operator himpunan yang berbeda diperlakukan sama dan tidak ada yang didahulukan dari yang lain. Ini adalah masalah ketika Anda memigrasikan aplikasi dari Oracle ke MariaDB, dan yang lebih buruk, perbedaan ini agak sulit ditemukan. Tidak ada kesalahan yang dihasilkan dan data dikembalikan dan, dalam banyak kasus, data yang benar dikembalikan. Namun, dalam beberapa kasus, di mana data seperti pada contoh kami di atas, data yang salah dikembalikan, yang merupakan masalah.

Pengaruh pada Migrasi Data

Jadi bagaimana kita menghadapi ini jika kita memigrasikan aplikasi dari Oracle ke MariaDB? Ada beberapa opsi:

  • Tulis ulang aplikasi sehingga mengasumsikan bahwa data yang dikembalikan dari kueri seperti ini sejalan dengan Standar SQL dan MariaDB.
  • Tulis ulang pernyataan SQL, menggunakan tanda kurung, sehingga MariaDB mengembalikan data yang sama dengan Oracle
  • Atau, dan ini adalah cara paling cerdas, gunakan SQL_MODE=Oracle MariaDB pengaturan.

Untuk cara terakhir, dan paling cerdas, agar berfungsi, kita perlu menjalankan dengan MariaDB 10.3.7 atau lebih tinggi (ini disarankan oleh Anda benar-benar di https://jira.mariadb.org/browse/MDEV-13695). Mari kita periksa cara kerjanya. Bandingkan hasil SELECT . ini dengan Oracle yang di atas (yang menghasilkan hasil yang sama) dan yang dari MariaDB di atasnya (yang tidak):

 MariaDB> atur SQL_MODE=Oracle; Kueri OK, 0 baris terpengaruh (0,001 detik) MariaDB> SELECT i.prod_id, p.prod_name -> FROM inventory i JOIN products p ON i.prod_id =p.id -> UNION -> SELECT oi.prod_id, p.prod_name -> FROM order_items oi JOIN products p ON oi.prod_id =p.id -> INTERSECT -> SELECT d.prod_id, p.prod_name -> FROM delivery d JOIN products p ON d.prod_id =p.id; +---------+------------+ | prod_id | nama_prod | +---------+------------+ | 2 | Vas Merah | | 3 | Karpet Merah | +---------+------------+ 2 baris dalam set (0,002 detik)

Seperti yang Anda lihat, ketika SQL_MODE diatur ke Oracle , MariaDB benar-benar berperilaku seperti Oracle. Ini bukan satu-satunya hal yang SQL_MODE=Oracle tentu saja, tetapi ini adalah salah satu area yang kurang dikenal.

Kesimpulan

Operator yang ditetapkan INTERSECT dan EXCEPT tidak banyak digunakan, meskipun mereka muncul di sana-sini, dan ada beberapa kegunaan untuk mereka. Contoh di blog ini lebih untuk menggambarkan cara kerja operator ini daripada menunjukkan kegunaan yang sangat baik untuk mereka. Mungkin ada contoh yang lebih baik. Ketika Anda bermigrasi dari Oracle ke MariaDB, operator set SQL sangat berguna karena banyak aplikasi Oracle menggunakannya, dan seperti yang dapat dilihat, MariaDB dapat ditipu untuk bekerja seperti Oracle, yang non-Standar tetapi tetap memiliki tujuan. Namun, secara default, tentu saja MariaDB berfungsi sebagaimana mestinya dan mengikuti Standar SQL.

Selamat SQL'ing
/Karlsson


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana CHAR_LENGTH() Bekerja di MariaDB

  2. Pengantar Pencarian Teks Lengkap di MariaDB

  3. Panduan untuk Indeks MySQL

  4. Bagaimana RTRIM() Bekerja di MariaDB

  5. Tips dan Trik untuk Menerapkan Kontrol Akses Berbasis Peran Database untuk MariaDB