MySQL "क्वेरी में नहीं"


181

मैं उन सभी पंक्तियों को फेंकने के लिए एक साधारण क्वेरी चलाना चाहता था Table1जहाँ एक प्रमुख तालिका मान किसी अन्य तालिका के कॉलम में मौजूद नहीं है (Table2 ) ।

मैंने प्रयोग करने की कोशिश की:

SELECT * FROM Table1 WHERE Table1.principal NOT IN Table2.principal

इसके बजाय एक वाक्यविन्यास त्रुटि फेंक रहा है। Google खोज ने मुझे उन मंचों पर ले जाया जहां लोग कह रहे थे कि MySQL समर्थन नहीं करता है NOT INऔर कुछ अत्यंत जटिल चीजों का उपयोग करने की आवश्यकता है। क्या ये सच है? या मैं एक भयावह गलती कर रहा हूँ?


1
और क्या होगा अगर मुझे तीन तालिकाओं से समान डेटा चाहिए। मेरा मतलब है कि एक तालिका 1 में 2000 प्रविष्टियाँ हैं, अन्य दो तालिकाएँ 2 और 3 में से प्रत्येक में 500 प्रविष्टियाँ हैं, उन सभी में सामान्य क्षेत्र 'नाम' है। हम तालिका 1 से सभी विवरण कैसे प्राप्त कर सकते हैं जो 'नाम' के आधार पर तालिका 2 और 3 में मौजूद नहीं हैं। हम दो बार में उपयोग नहीं कर सकते हैं, अगर ऐसा कैसे ..?

जवाबों:


310

IN का उपयोग करने के लिए, आपके पास एक सेट होना चाहिए, इस सिंटैक्स का उपयोग करें:

SELECT * FROM Table1 WHERE Table1.principal NOT IN (SELECT principal FROM table2)

85
सावधान जब table2.principalहो सकता है NULL। उस मामले NOT INमें हमेशा वापस आ जाएगा FALSEक्योंकि NOT INके रूप में इलाज किया जाता है <> ALL, जो कि उप-प्रकार से सभी पंक्तियों की तुलना करता है , जो कि तुलना करने पर Table1.principal <> table2.principalविफल रहता है NULL: Table1.principal <> NULLमें परिणाम नहीं होगा TRUE। ठीक करने के लिए NOT IN (SELECT principal FROM table2 WHERE principal IS NOT NULL):।
बस्ती

4
टिप्पणी के लिए धन्यवाद @ बस्ती! यह समझने में बहुत समय बिताया कि क्वेरी अपेक्षा के अनुरूप काम क्यों नहीं कर रही थी।
गौरव २३'१६

3
'NOT IN' सूची के अंदर 'Select *' का उपयोग करने से बचें। आपको एक विशेष कॉलम चुनना होगा। अन्यथा आपको यह त्रुटि मिलेगी: stackoverflow.com/questions/14046838/…
लोरिएन ब्रुने

165

उपशमन विकल्प पहले ही उत्तर दिया जा चुका है, लेकिन ध्यान दें कि कई मामलों में LEFT JOINऐसा करने का एक तेज़ तरीका हो सकता है:

SELECT table1.*
FROM table1 LEFT JOIN table2 ON table2.principal=table1.principal
WHERE table2.principal IS NULL

यदि आप यह सुनिश्चित करने के लिए कई तालिकाओं की जाँच करना चाहते हैं कि यह किसी तालिका में मौजूद नहीं है (जैसे SRKR की टिप्पणी में), तो आप इसका उपयोग कर सकते हैं:

SELECT table1.*
FROM table1
LEFT JOIN table2 ON table2.name=table1.name
LEFT JOIN table3 ON table3.name=table1.name
WHERE table2.name IS NULL AND table3.name IS NULL

2
मेरे अपने परीक्षण में, दोनों के लिए एक ही प्रदर्शन किया था NOT INऔर LEFT JOIN। +1 दोनों
बफ़रस्टैक

एक बार क्वेरी चलाने के बाद एक बार आपको वही परिणाम प्राप्त करने चाहिए जो आंतरिक DB कैशिंग के कारण नहीं हैं
Toote

मेरे लिए प्रदर्शन बेहतर था। मैं विभिन्न तालिकाओं के माध्यम से भागा, जबकि उनके पास विदेशी चाबियां थीं।
कीनोरा फ्लफ़बॉल

36

माईएसक्यूएल में बनाम जॉइस / आईएस नॉट बनाम एक्ज़िट्स बनाम नॉट आउट

MySQL, साथ ही SQL Server को छोड़कर अन्य सभी सिस्टम, मिलान मूल्य मिलते ही वापस लौटने के लिए LEFT JOIN/IS NULL को ऑप्टिमाइज़ करने में सक्षम FALSEहै, और यह एकमात्र सिस्टम है जो इस व्यवहार को दस्तावेज करने के लिए देखभाल करता है। […] चूंकि MySQL एल्गोरिदम का उपयोग करने HASHऔर MERGEइसमें शामिल होने में सक्षम नहीं है, केवल ANTI JOINयह सक्षम हैNESTED LOOPS ANTI JOIN

[...]

अनिवार्य रूप से, [ NOT IN] ठीक वही योजना है जो LEFT JOIN/ IS NULLउपयोग करता है, इस तथ्य के बावजूद कि इन योजनाओं को कोड की विभिन्न शाखाओं द्वारा निष्पादित किया जाता है और वे परिणामों के परिणामों में अलग दिखते हैं EXPLAIN। एल्गोरिदम वास्तव में समान हैं और क्वेरी एक ही समय में पूरी होती हैं।

[...]

[उपयोग करते समय प्रदर्शन ड्रॉप NOT EXISTS] का सटीक कारण बताना कठिन है , क्योंकि यह ड्रॉप रैखिक है और डेटा वितरण, दोनों तालिकाओं में मूल्यों की संख्या आदि पर निर्भर नहीं करता है, जब तक कि दोनों क्षेत्रों को अनुक्रमित नहीं किया जाता है। चूंकि MySQL में कोड के तीन टुकड़े होते हैं जो आवश्यक रूप से एक काम करते हैं, यह संभव है कि कोड के लिए जिम्मेदार EXISTSकिसी तरह की अतिरिक्त जांच करता है जो अतिरिक्त समय लेता है।

[...]

MySQL एक तरह का करने के लिए सभी तीन तरीकों का अनुकूलन कर सकता है NESTED LOOPS ANTI JOIN। […] हालाँकि, ये तीन विधियाँ तीन अलग-अलग योजनाएँ उत्पन्न करती हैं जिन्हें तीन अलग-अलग कोड द्वारा निष्पादित किया जाता है। कोड, जो EXISTSविधेय को निष्पादित करता है, लगभग 30% कम कुशल है […]

यही कारण है कि MySQL में लापता मूल्यों की खोज करने का सबसे अच्छा तरीका एक LEFT JOIN/ IS NULLया के NOT INबजाय का उपयोग कर रहा है NOT EXISTS

(emphases जोड़ा गया)


7

दुर्भाग्य से यह "नॉट इन" क्लॉज के MySql उपयोग के साथ एक मुद्दा प्रतीत होता है, नीचे दिया गया स्क्रीन-शूट गलत परिणाम लौटाने वाले उप-क्वेरी विकल्प को दिखाता है:

mysql> show variables like '%version%';
+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| innodb_version          | 1.1.8                        |
| protocol_version        | 10                           |
| slave_type_conversions  |                              |
| version                 | 5.5.21                       |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | Linux                        |
+-------------------------+------------------------------+
7 rows in set (0.07 sec)

mysql> select count(*) from TABLE_A where TABLE_A.Pkey not in (select distinct TABLE_B.Fkey from TABLE_B );
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.07 sec)

mysql> select count(*) from TABLE_A left join TABLE_B on TABLE_A.Pkey = TABLE_B.Fkey where TABLE_B.Pkey is null;
+----------+
| count(*) |
+----------+
|      139 |
+----------+
1 row in set (0.06 sec)

mysql> select count(*) from TABLE_A where NOT EXISTS (select * FROM TABLE_B WHERE TABLE_B.Fkey = TABLE_A.Pkey );
+----------+
| count(*) |
+----------+
|      139 |
+----------+
1 row in set (0.06 sec)

mysql> 

7

Be carefull के NOT INलिए एक उपनाम नहीं है <> ANY, लेकिन के लिए <> ALL!

http://dev.mysql.com/doc/refman/5.0/en/any-in-some-subqueries.html

SELECT c FROM t1 LEFT JOIN t2 USING (c) WHERE t2.c IS NULL

कठबोली 'द्वारा प्रतिस्थापित किया जा सकता है

SELECT c FROM t1 WHERE c NOT IN (SELECT c FROM t2)

तुम्हें अवश्य उपयोग करना चाहिए

SELECT c FROM t1 WHERE c <> ANY (SELECT c FROM t2)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.