सेट ऑपरेटर एसक्यूएल ऑपरेटर हैं जो अलग-अलग तरीकों से अलग-अलग परिणाम सेट के संयोजन से निपटते हैं। मान लें कि आपके पास दो अलग-अलग हैं SELECT
s जिसे आप एकल परिणाम सेट में संयोजित करना चाहते हैं, सेट ऑपरेटर खेल में आते हैं। MariaDB UNION
. का समर्थन करता रहा है और UNION ALL
लंबे समय तक ऑपरेटर सेट करें, और ये अब तक के सबसे सामान्य SQL सेट ऑपरेटर हैं।
लेकिन हम यहां खुद से आगे निकल रहे हैं, मुझे पहले एसक्यूएल सेट ऑपरेटरों के बारे में बताएं जो हमारे पास हैं और वे कैसे काम करते हैं। यदि आप इसे आजमाना चाहते हैं, तो आप अपने मौजूदा मारियाडीबी सर्वर की तैनाती का उपयोग कर सकते हैं, या मारियाडीबी स्काईएसक्यूएल क्लाउड डेटाबेस में इसे आजमा सकते हैं।
यूनियन और यूनियन ऑल
UNION
और UNION ALL
सेट ऑपरेटर दो या दो से अधिक परिणाम सेट का परिणाम जोड़ते हैं। आइए UNION ALL
से शुरू करते हैं और UNION
तब UNION ALL
. का एक रूपांतर होगा ।
आइए देखें कि यह SQL में कैसा दिखता है। आइए मान लें कि हम एक वेबशॉप चलाते हैं और हम जो उत्पाद बेचते हैं, उनके लिए हमारे पास एक इन्वेंट्री है। अब हम उन सभी उत्पादों को देखना चाहते हैं जो ऑर्डर पर हैं या इन्वेंट्री में हैं, इसके लिए एक क्वेरी कुछ इस तरह दिखाई देगी:
SELECT oi.prod_id, p.prod_name FROM order_items oi JOIN products p ON oi.prod_id = p.id UNION ALL SELECT i.prod_id, p.prod_name FROM inventory i JOIN products p ON i.prod_id = p.id;
यह, सेट थ्योरी में, UNION
है उत्पादों के सेट जिन्हें ऑर्डर किया गया है और उत्पादों के सेट जो इन्वेंट्री में हैं। जो सैद्धांतिक रूप से ठीक है, लेकिन इस क्वेरी के परिणाम के साथ एक समस्या है। मुद्दा यह है कि एक उत्पाद जो ऑर्डर और इन्वेंट्री दोनों में या इन्वेंट्री में कई स्थानों पर दिखाई देता है, आउटपुट में एक से अधिक बार दिखाई देगा। यही कारण है कि UNION ALL
अधिक उपयोग नहीं किया जाता है और इसके बजाय UNION DISTINCT
(DISTINCT
डिफ़ॉल्ट है और इसे अनदेखा किया जा सकता है) का उपयोग किया जाता है। उदाहरण के लिए:
SELECT oi.prod_id, p.prod_name FROM order_items oi JOIN products p ON oi.prod_id = p.id UNION SELECT i.prod_id, p.prod_name FROM inventory i JOIN products p ON i.prod_id = p.id;
इस क्वेरी के साथ, एक उत्पाद जो या तो ऑर्डर पर है या इन्वेंट्री में मौजूद है, केवल एक बार सूचीबद्ध होता है। ध्यान दें कि जब हम यहां डुप्लीकेट हटा रहे हैं, तो यह उन मानों की तुलना की जाती है, इसलिए एक ही कॉलम में समान मान वाली दो पंक्तियों को समान माना जाता है, भले ही मान अलग-अलग तालिकाओं या स्तंभों से आते हों।
हालांकि ईमानदार होने के लिए, उपरोक्त क्वेरी में ऐसा कुछ भी नहीं है जो नियमित SELECT
के साथ नहीं किया जा सकता है उत्पादों . से टेबल और कुछ जुड़ते हैं। कुछ मायनों में एक UNION
पढ़ने में आसान हो सकता है। दूसरी ओर, यदि हम ऑर्डर पर या इन्वेंट्री में उत्पादों की एक सूची रखना चाहते हैं, और यह भी जानना चाहते हैं कि यह कौन सा था, तो एक प्रश्न कुछ इस तरह होगा:
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;
यहाँ एक प्रश्न है जो एक साधारण SELECT
. के साथ करना आसान नहीं है उत्पादों . से तालिका के रूप में हम उत्पाद तालिका से एक ही पंक्ति को दो बार देख रहे हैं (एक बार order_items के लिए) और एक बार इन्वेंट्री . के लिए )।
अधिक SQL सेट ऑपरेटर
मारियाडीबी सर्वर 10.3 के साथ दो नए एसक्यूएल सेट ऑपरेटर आए, जो बड़े पैमाने पर ओरेकल संगतता बढ़ाने के लिए पेश किए गए थे, लेकिन ये ऑपरेटर अपने आप में उपयोगी हैं। मारियाडीबी सर्वर 10.4 तब सेट ऑपरेटर वरीयता को नियंत्रित करने की क्षमता जोड़ता है। हम उस पर भी नजर डालेंगे। ऑपरेटर की प्राथमिकता को नियंत्रित करने की क्षमता के बिना, सेट ऑपरेटर हमेशा वैसा काम नहीं करते जैसा आप चाहते हैं या उम्मीद करते हैं।
नए SQL सेट ऑपरेटर हैं INTERSECT
और EXCEPT
और वे उपयोगी होते हैं, खासकर एनालिटिक्स का उपयोग करते समय। साथ ही, हालांकि JOIN
s और अन्य निर्माणों का अक्सर उपयोग किया जा सकता है, SQL सेट ऑपरेटर एक SQL सिंटैक्स की अनुमति देते हैं जो पढ़ने और समझने में आसान हो सकता है। और, यदि आपके पास Oracle अनुप्रयोग हैं तो आप MariaDB में माइग्रेट कर रहे हैं, इन ऑपरेटरों की उपयोगिता स्पष्ट है।
इंटरसेक्ट सेट ऑपरेटर
INTERSECT
ऑपरेटर दो या दो से अधिक सेटों में मौजूद सभी आइटम लौटाएगा, या SQL शब्दों में, सभी पंक्तियाँ जो दो परिणाम सेटों में मौजूद हैं। इस मामले में, आइटम के दो सेटों का एक क्रॉस सेक्शन बनाया जाता है। SQL शब्दों में इसका अर्थ है कि केवल दोनों सेटों में मौजूद पंक्तियाँ ही लौटाई जाती हैं, इसलिए यदि मैं यह जाँचना चाहता हूँ कि मेरे पास कौन से उत्पाद ऑर्डर पर हैं और जो इन्वेंट्री में भी हैं, तो एक क्वेरी इस तरह दिख सकती है:
SELECT 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;
फिर से, इस क्वेरी का निर्माण JOIN
. का उपयोग करके किया जा सकता है उत्पादों . पर तालिका, लेकिन ऊपर दी गई क्वेरी इस बारे में थोड़ी स्पष्ट है कि हम क्या हासिल करने की कोशिश कर रहे हैं।
EXCEPT सेट ऑपरेटर
EXCEPT
. के मामले में ऑपरेटर, हम उन वस्तुओं को चाहते हैं जो एक सेट में हैं, लेकिन दूसरे में नहीं। इसलिए, ऊपर दिए गए उदाहरण का उपयोग करते हुए, यदि हम उन उत्पादों को देखना चाहते हैं जो हमारे पास ऑर्डर पर हैं, लेकिन जिनके लिए हमारे पास इन्वेंट्री नहीं है, तो हम इस तरह से एक प्रश्न लिख सकते हैं:
SELECT oi.prod_id, p.prod_name FROM order_items oi JOIN products p ON oi.prod_id = p.id EXCEPT SELECT i.prod_id, p.prod_name FROM inventory i JOIN products p ON i.prod_id = p.id;
फिर से, इस विशेष क्वेरी को लिखने के अन्य तरीके भी हैं, लेकिन अन्य, अधिक उन्नत प्रश्नों के लिए जब हम दो अलग-अलग तालिकाओं से डेटा का संयोजन कर रहे हैं, तो ऐसा नहीं है।
एकाधिक सेट ऑपरेटरों का संयोजन
यदि यह उपयोगी है तो आप 2 से अधिक सेट ऑपरेटरों को जोड़ सकते हैं। उदाहरण के लिए, आइए देखें कि क्या हमें ऐसे उत्पाद मिल सकते हैं जो ऑर्डर पर हैं और डिलीवर हो चुके हैं या स्टॉक में हैं। इसके लिए SQL कुछ इस तरह दिखेगा:
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 deliveries 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;पर उत्पादों में शामिल हों
इसे सरल भाषा में व्यक्त करने के लिए, क्या चल रहा है कि मैं पहले जांचता हूं कि कौन से उत्पाद ऑर्डर पर हैं और जिन्हें डिलीवर किया गया है, और फिर मैं उत्पादों के इस सेट को इन्वेंट्री में सभी उत्पादों के साथ जोड़ देता हूं। कोई भी उत्पाद जो परिणाम सेट में नहीं है इन्वेंट्री में नहीं है लेकिन ऑर्डर पर हो सकता है या डिलीवर हो सकता है, लेकिन दोनों नहीं।
लेकिन अब, इसे अलग तरह से व्यक्त करते हैं, और देखते हैं कि क्या होता है। मुझे उन सभी उत्पादों की सूची चाहिए जो स्टॉक में हैं या डिलीवर हो चुके हैं और ऑर्डर पर हैं। तब SQL कुछ इस तरह होगा, ऊपर दिए गए SQL के समान लेकिन थोड़ा अलग:
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 deliveries d JOIN products p ON d.prod_id = p.id;
फिर आप इसकी व्याख्या कैसे करते हैं? क्या आप उन उत्पादों को सूचीबद्ध करते हैं जो स्टॉक में हैं और जो ऑर्डर पर हैं और जो उत्पाद वितरित किए जा रहे हैं? यही दिखता है, है ना? यह बस इतना ही है INTERSECT
(और EXCEPT
उस मामले के लिए) की वरीयता . है UNION
. से अधिक . दो SQL कथन एक ही परिणाम सेट का उत्पादन करते हैं, कम से कम MariaDB में और इस प्रकार SQL मानक कहता है कि चीजों को काम करना चाहिए। लेकिन एक अपवाद है, Oracle।
यह Oracle में कैसे काम करता है
Oracle के पास सभी चार SQL सेट ऑपरेटर हैं (UNION
, UNION ALL
, INTERSECT
और EXCEPT
) लंबे समय तक, मानकीकृत होने से बहुत पहले, इसलिए उनका कार्यान्वयन थोड़ा अलग है। आइए उपरोक्त तालिकाओं के साथ प्रयास करें और उनमें कुछ डेटा डालें। डेटा बहुत सरल है और इतनी सफल कंपनी को नहीं दर्शाता है, लेकिन यह एक उदाहरण के रूप में काम करता है, और हम यहां केवल प्रासंगिक कॉलम दिखा रहे हैं।
तालिका | उत्पाद | order_items | इन्वेंट्री | वितरण | ||
स्तंभ | prod_id | prod_name | order_id | prod_id | prod_id | prod_id |
डेटा | 1 | फूलदान नीला | 1 | 1 | 1 | 2 |
2 | फूलदान लाल | 2 | 1 | 2 | 3 | |
3 | कालीन लाल | 2 | 3 |
डेटा के साथ, आइए उस अंतिम SQL कथन को फिर से देखें। एक विशेषता है जो आपको प्राथमिकता को नियंत्रित करने की अनुमति देती है, और वह है कोष्ठक, या कोष्ठक का उपयोग करना (मारियाडीबी 10.4 में प्रस्तुत, देखें https://jira.mariadb.org/browse/MDEV-11953), और इनका उपयोग करके वर्णन करने के लिए क्या हो रहा है, बयान इस तरह दिखेगा:
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 deliveries d JOIN products p ON d.prod_id = p.id); +---------+------------+ | prod_id | prod_name | +---------+------------+ | 1 | Vase Blue | | 2 | Vase Red | | 3 | Carpet Red | +---------+------------+ 3 rows in set (0.001 sec)
अब, क्वेरी के तीन घटकों को सख्त क्रम में संचालित करने के लिए लागू करने के लिए उसी तकनीक का उपयोग करें:
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 deliveries d JOIN products p ON d.prod_id = p.id; +---------+------------+ | prod_id | prod_name | +---------+------------+ | 2 | Vase Red | | 3 | Carpet Red | +---------+------------+ 2 rows in set (0.001 sec)
और अंत में बिना कोष्ठक के:
MariaDB [test]> 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 deliveries d JOIN products p ON d.prod_id = p.id; +---------+------------+ | prod_id | prod_name | +---------+------------+ | 1 | Vase Blue | | 2 | Vase Red | | 3 | Carpet Red | +---------+------------+ 3 rows in set (0.001 sec)
हम देखते हैं कि मारियाडीबी ने मानक का पालन करते हुए मान लिया कि INTERSECT
UNION
. से अधिक प्राथमिकता है . जो हमें Oracle में लाता है। आइए उपरोक्त SQL को sqlplus का उपयोग करके Oracle में आज़माएँ:
SQL> SELECT 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 SELECT d.prod_id, p.prod_name 8 FROM deliveries d JOIN products p ON d.prod_id = p.id; PROD_ID PROD_NAME ---------- ------------------------------ 2 Vase Red 3 Carpet Red
यहाँ क्या हो रहा है, आप पूछें? खैर, Oracle मानक का पालन नहीं करता है। विभिन्न सेट ऑपरेटरों को समान माना जाता है और दूसरे पर किसी की प्राथमिकता नहीं होती है। यह एक समस्या है जब आप Oracle से MariaDB में एप्लिकेशन माइग्रेट कर रहे हैं, और इससे भी बुरी बात यह है कि यह अंतर खोजना मुश्किल है। कोई त्रुटि उत्पन्न नहीं होती है और डेटा वापस कर दिया जाता है और कई मामलों में, सही डेटा वापस कर दिया जाता है। लेकिन, कुछ मामलों में, जहां डेटा ऊपर हमारे उदाहरण की तरह है, गलत डेटा लौटा दिया जाता है, जो एक समस्या है।
डेटा माइग्रेट करने पर प्रभाव
तो अगर हम Oracle से MariaDB में किसी एप्लिकेशन को माइग्रेट कर रहे हैं तो हम इससे कैसे निपटेंगे? कुछ विकल्प हैं:
- एप्लिकेशन को फिर से लिखें ताकि यह मान लिया जाए कि इस तरह की क्वेरी से लौटाया गया डेटा SQL मानक और मारियाडीबी के अनुरूप है।
- कोष्ठक का उपयोग करके SQL कथनों को फिर से लिखें, ताकि MariaDB Oracle के समान डेटा लौटाए
- या, और यह सबसे चतुर तरीका है, MariaDB
SQL_MODE=Oracle
का उपयोग करें सेटिंग।
काम करने के लिए आखिरी और सबसे स्मार्ट तरीके के लिए, हमें मारियाडीबी 10.3.7 या उच्चतर के साथ चलने की जरूरत है (यह आपके द्वारा वास्तव में https://jira.mariadb.org/browse/MDEV-13695 में सुझाया गया था)। आइए देखें कि यह कैसे काम करता है। इस के परिणाम की तुलना करें SELECT
Oracle के साथ एक ऊपर (जो समान परिणाम उत्पन्न करता है) और उसके ऊपर MariaDB से एक (जो नहीं):
MariaDB> set SQL_MODE=Oracle; Query OK, 0 rows affected (0.001 sec) 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 deliveries d JOIN products p ON d.prod_id = p.id; +---------+------------+ | prod_id | prod_name | +---------+------------+ | 2 | Vase Red | | 3 | Carpet Red | +---------+------------+ 2 rows in set (0.002 sec)
जैसा कि आप देख सकते हैं, जब SQL_MODE
Oracle
. पर सेट है , मारियाडीबी वास्तव में ओरेकल की तरह व्यवहार करता है। केवल यही एक चीज नहीं है जो SQL_MODE=Oracle
जाहिर है, लेकिन यह कम ज्ञात क्षेत्रों में से एक है।
निष्कर्ष
सेट ऑपरेटर INTERSECT
और EXCEPT
इतना उपयोग नहीं किया जाता है, हालांकि वे यहां और वहां दिखाई देते हैं, और उनके लिए कुछ उपयोग हैं। इस ब्लॉग में उदाहरण यह बताने के लिए और भी हैं कि ये ऑपरेटर उनके लिए वास्तव में अच्छे उपयोग दिखाने के बजाय कैसे काम करते हैं। शायद बेहतर उदाहरण हैं। जब आप Oracle से MariaDB में माइग्रेट कर रहे होते हैं, तो SQL सेट ऑपरेटर वास्तव में उपयोगी होते हैं क्योंकि कई Oracle एप्लिकेशन उनका उपयोग करते हैं, और जैसा कि देखा जा सकता है, MariaDB को Oracle की तरह ही काम करने के लिए धोखा दिया जा सकता है, जो गैर-मानक है लेकिन फिर भी एक उद्देश्य को पूरा करता है। लेकिन, डिफ़ॉल्ट रूप से, निश्चित रूप से मारियाडीबी एसक्यूएल मानक की तरह काम करता है और उसका पालन करता है।
हैप्पी SQL'ing
/कार्लसन