SQL में EXISTS और IN के बीच अंतर?


443

SQL में EXISTSऔर INclause में क्या अंतर है ?

हमें कब उपयोग करना चाहिए EXISTS, और हमें कब उपयोग करना चाहिए IN?

जवाबों:


224

existsकीवर्ड कि रास्ते में इस्तेमाल किया जा सकता है, लेकिन वास्तव में इसे से बचने के गिनती के लिए एक रास्ता के रूप में इरादा है:

--this statement needs to check the entire table
select count(*) from [table] where ...

--this statement is true as soon as one match is found
exists ( select * from [table] where ... )

यह सबसे उपयोगी है जहां आपके पास ifसशर्त बयान हैं, क्योंकि इससे existsबहुत तेज हो सकता है count

सबसे inअच्छा उपयोग किया जाता है जहां आपके पास पास करने के लिए एक स्थिर सूची है:

 select * from [table]
 where [field] in (1, 2, 3)

जब आपके पास एक inबयान में एक तालिका होती है तो यह एक का उपयोग करने के लिए अधिक समझ में आता है join, लेकिन ज्यादातर यह बात नहीं होनी चाहिए। क्वेरी ऑप्टिमाइज़र को उसी तरह की योजना वापस करनी चाहिए। कुछ कार्यान्वयन में (ज्यादातर पुराने, जैसे Microsoft SQL सर्वर 2000) inक्वेरीज़ को हमेशा नेस्टेड जॉइन प्लान मिलेगा , जबकि joinक्वेश्चन नेस्टेड, मर्ज या हैश का उपयोग उचित होगा। अधिक आधुनिक कार्यान्वयन चालाक होते हैं और योजना inका उपयोग किए जाने पर भी समायोजित कर सकते हैं ।


2
क्या आप इस बारे में विस्तार से बता सकते हैं कि "जब आपके पास एक बयान में एक तालिका होती है तो इससे जुड़ने का उपयोग करने के लिए अधिक समझ में आता है, लेकिन यह वास्तव में कोई फर्क नहीं पड़ता। क्वेरी ऑप्टिमाइज़र उसी तरह की योजना को वापस कर देगा।" क्वेरी ऑप्टिमाइज़र भाग नहीं, वह भाग जहाँ आप JOINप्रतिस्थापन के रूप में उपयोग कर सकते हैं IN
दूरथेर

select * from [table] where [field] in (select [field] from [table2])के रूप में एक ही परिणाम (और क्वेरी योजना) देता है select * from [table] join [table2] on [table2].[field] = [table].[field]

@ यह नहीं है: पहली क्वेरी से सभी कॉलम लौटाता है table, जबकि दूसरा सब कुछ tableऔर से वापस करता है table2। कुछ (अधिकतर पुराने) SQL डेटाबेस में inक्वेरी को नेस्टेड जॉइन के रूप में लागू किया जाएगा, जबकि joinक्वेरी को नेस्टेड, मर्ज, हैशेड, आदि - जो भी सबसे तेज हो।
कीथ

2
ठीक है, मुझे चयनित क्लॉज़ में कॉलम निर्दिष्ट करना चाहिए, लेकिन आपको अपना उत्तर अपडेट करना चाहिए क्योंकि यह स्पष्ट रूप से बताता है कि क्वेरीज़ "किसी भी तरह से उसी योजना को वापस कर देगा"।

existsएक केस स्टेटमेंट के भीतर इस्तेमाल किया जा सकता है, इसलिए वे इस तरह से भी काम कर सकते हैंselect case when exists (select 1 from emp where salary > 1000) then 1 else 0 end as sal_over_1000
smooth_smoothie

125

EXISTSआपको बताएगा कि कोई क्वेरी किसी भी परिणाम पर लौटी है या नहीं। उदाहरण के लिए:

SELECT * 
FROM Orders o 
WHERE EXISTS (
    SELECT * 
    FROM Products p 
    WHERE p.ProductNumber = o.ProductNumber)

IN एक मूल्य की तुलना कई से करने के लिए किया जाता है, और इस तरह शाब्दिक मूल्यों का उपयोग कर सकते हैं:

SELECT * 
FROM Orders 
WHERE ProductNumber IN (1, 10, 100)

आप INक्लॉज़ के साथ क्वेरी परिणाम का उपयोग कर सकते हैं , जैसे:

SELECT * 
FROM Orders 
WHERE ProductNumber IN (
    SELECT ProductNumber 
    FROM Products 
    WHERE ProductInventoryQuantity > 0)

3
अंतिम प्रश्न खतरनाक है क्योंकि यह मामले में विफल हो सकता है उपकुंजी किसी भी परिणाम को वापस नहीं करता है। 'इन क्लॉज के लिए कम से कम 1 तर्क की आवश्यकता होती है ...
user2054927

40
@ user2054927 अंतिम क्वेरी सही ढंग से कोई पंक्तियाँ नहीं लौटाएगी यदि उपकुंजी कोई पंक्तियाँ नहीं लौटाती है - इसके बारे में कुछ भी खतरनाक नहीं है!
टोनी एंड्रयूज

सबसे अच्छा जवाब।
अमिनावड ग्लिक्सेटिन

81

नियम अनुकूलक के आधार पर :

  • EXISTSINजब उप-क्वेरी परिणाम बहुत बड़े होते हैं , तो बहुत तेजी से होता है।
  • INEXISTSजब उप-क्वेरी परिणाम बहुत छोटा होता है , तो तेजी से होता है।

लागत अनुकूलक के आधार पर :

  • इसमें कोई फर्क नही है।

21
आपके तर्क का प्रमाण? मुझे नहीं लगता कि IN कभी EXISTS की तुलना में तेज़ होगा!
नवाज़

22
@ नवाज सबूत के बारे में कि IN हमेशा EXISTS से धीमा क्यों है?
छत

2
बुरी तरह से लागू किया गया क्वेरी ऑप्टिमाइज़र? मुझे कुछ ऐसा लगता है (हालाँकि यह स्थिति बिल्कुल नहीं है) एक निश्चित RDBMs में होती है ...
Haroldo_OK

1
EXISTS विशुद्ध रूप से बूलियन मान लौटाता है, जो बीआईटी / बुलियन प्रकार की तुलना में बड़े तार या मूल्यों की तुलना में हमेशा तेज होता है। IN या बूलियन तुलना नहीं हो सकती है। चूंकि प्रोग्रामिंग स्थिरता (ACID का हिस्सा) के लिए EXPLICIT उपयोग को प्राथमिकता देता है, EXISTS को आम तौर पर पसंद किया जाता है।
clifton_h

2
इसे इतनी बार क्यों उखाड़ा गया? इस धारणा-आधारित कथन को आम तौर पर सत्य होना चाहिए, इसका कोई कारण नहीं है।
लुकास एडर

40

मैं मान रहा हूं कि आप जानते हैं कि वे क्या करते हैं, और इस तरह से अलग-अलग तरीके से उपयोग किया जाता है, इसलिए मैं आपके प्रश्न को समझने जा रहा हूं: जब EXISTS, या इसके विपरीत में SQL का उपयोग करने के लिए फिर से लिखना एक अच्छा विचार होगा।

क्या यह एक उचित धारणा है?


संपादित करें : मैं जो कारण पूछ रहा हूं, वह यह है कि कई मामलों में आप इसके बजाय एक EXISTS का उपयोग करने के लिए IN पर आधारित SQL फिर से लिख सकते हैं, और इसके विपरीत, और कुछ डेटाबेस इंजन के लिए, क्वेरी ऑप्टिमाइज़र दो अलग तरह से व्यवहार करेगा।

उदाहरण के लिए:

SELECT *
FROM Customers
WHERE EXISTS (
    SELECT *
    FROM Orders
    WHERE Orders.CustomerID = Customers.ID
)

के लिए फिर से लिखा जा सकता है:

SELECT *
FROM Customers
WHERE ID IN (
    SELECT CustomerID
    FROM Orders
)

या शामिल होने के साथ:

SELECT Customers.*
FROM Customers
    INNER JOIN Orders ON Customers.ID = Orders.CustomerID

तो मेरा सवाल अभी भी खड़ा है, क्या मूल पोस्टर सोच रहा है कि IN और EXISTS क्या करता है, और इस प्रकार इसका उपयोग कैसे करना है, या क्या वह wether को एक SQL का उपयोग करके INISISTS का उपयोग करने के लिए, या इसके विपरीत, एक अच्छा विचार होगा?


12
मैं ओपी के बारे में नहीं जानता, लेकिन मैं इस प्रश्न का उत्तर चाहूंगा! जब मैं आईडी लौटाता हूं, तो एक सब-वे के साथ IN के बजाय EXISTS का उपयोग कब करना चाहिए?
रॉय टिंकर

8
में JOIN, आपको DISTINCT
18 में

4
महान प्रदर्शन, लेकिन बहुत ज्यादा सवाल अनुत्तरित छोड़ दें
Junchen लियू

28
  1. EXISTSINजब उपकेंद्र के परिणाम बहुत बड़े होते हैं तो बहुत तेजी से होता है। जब उपकेंद्र के परिणाम बहुत छोटे
    INहोते हैं, EXISTSतो तेजी से होता है।

    CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT)
    GO
    CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20))
    GO
    
    INSERT INTO t1
    SELECT 1, 'title 1', 5 UNION ALL
    SELECT 2, 'title 2', 5 UNION ALL
    SELECT 3, 'title 3', 5 UNION ALL
    SELECT 4, 'title 4', 5 UNION ALL
    SELECT null, 'title 5', 5 UNION ALL
    SELECT null, 'title 6', 5
    
    INSERT INTO t2
    SELECT 1, 1, 'data 1' UNION ALL
    SELECT 2, 1, 'data 2' UNION ALL
    SELECT 3, 2, 'data 3' UNION ALL
    SELECT 4, 3, 'data 4' UNION ALL
    SELECT 5, 3, 'data 5' UNION ALL
    SELECT 6, 3, 'data 6' UNION ALL
    SELECT 7, 4, 'data 7' UNION ALL
    SELECT 8, null, 'data 8' UNION ALL
    SELECT 9, 6, 'data 9' UNION ALL
    SELECT 10, 6, 'data 10' UNION ALL
    SELECT 11, 8, 'data 11'
  2. प्रश्न 1

    SELECT
    FROM    t1 
    WHERE   not  EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id)

    प्रश्न २

    SELECT t1.* 
    FROM   t1 
    WHERE  t1.id not in (SELECT  t2.t1id FROM t2 )

    यदि t1आपकी आईडी में शून्य मान है, तो क्वेरी 1 उन्हें मिल जाएगी, लेकिन क्वेरी 2 कठबोली शून्य मापदंडों को ढूंढती है।

    मेरा मतलब है कि INअशक्त के साथ किसी भी चीज की तुलना नहीं की जा सकती है, इसलिए इसमें अशक्त के लिए कोई परिणाम नहीं है, लेकिन EXISTSअशक्त के साथ सब कुछ की तुलना कर सकते हैं।


यह उत्तर टॉम की पतंग की भावना ( asktom.oracle.com/pls/asktom/… ) का यथोचित सारांश है
फ्रेंच

मुझे लगता है कि यह जवाब अंतर्ज्ञान पर आधारित है, जो काफी उचित है। लेकिन यह सार्वभौमिक रूप से सच नहीं हो सकता। उदाहरण के लिए, यह लगभग निश्चित रूप से नहीं का सच है Ingres अहम - - जब यह एक ही बात कई तरीके लेखन की बात आती है 'समृद्धि' है, जो दोनों बराबर एसक्यूएल प्रश्नों को पार्स होगा ही Quel क्वेरी, जो एसक्यूएल के अभाव है किया जाना है।
onedaywhen

ये 2 प्रश्न तार्किक रूप से समतुल्य हैं यदि केवल और यदि t2.id को "NOT NULL" के रूप में परिभाषित किया गया है। "से t1 कहां t1.id नहीं में (टी 2 से t2.id बॉक्स चुनें t1 *। तालिका परिभाषा में कोई निर्भरता के साथ समानक जागीरदार के 2 क्वेरी होना चाहिए जहां t2.id रिक्त नहीं है )"
डेविड דודו Markovitz

16

यदि आप INऑपरेटर का उपयोग कर रहे हैं , तो SQL इंजन आंतरिक क्वेरी से प्राप्त सभी रिकॉर्ड स्कैन करेगा। दूसरी ओर यदि हम उपयोग कर रहे हैं EXISTS, तो SQL इंजन एक मैच मिलते ही स्कैनिंग प्रक्रिया को रोक देगा।


10

IN केवल समानता संबंधों (या असमानता का समर्थन करता है जब पहले नहीं )।
यह = किसी भी / = कुछ , उदाहरण के लिए एक पर्याय है

select    * 
from      t1 
where     x in (select x from t2)
;

EXISTS विभिन्न प्रकार के संबंधों का समर्थन करता है, जिन्हें IN , जैसे का उपयोग करके व्यक्त नहीं किया जा सकता है -

select    * 
from      t1 
where     exists (select    null 
                  from      t2 
                  where     t2.x=t1.x 
                        and t2.y>t1.y 
                        and t2.z like '℅' || t1.z || '℅'
                  )
;

और एक अलग नोट पर -

EXISTS और IN के बीच कथित रूप से प्रदर्शन और तकनीकी अंतर विशिष्ट विक्रेता के कार्यान्वयन / सीमाओं / बगों के परिणामस्वरूप हो सकता है, लेकिन कई बार वे डेटाबेस इंटर्नल्स की समझ की कमी के कारण बनाए गए मिथकों के अलावा कुछ भी नहीं हैं।

तालिकाओं की परिभाषा, सांख्यिकी सटीकता, डेटाबेस कॉन्फ़िगरेशन और ऑप्टिमाइज़र के संस्करण का निष्पादन योजना पर सभी प्रभाव पड़ता है और इसलिए प्रदर्शन मीट्रिक पर।


प्रदर्शन पर आपकी टिप्पणी के लिए अपवोट करें: एक विशिष्ट DBMS पर ध्यान केंद्रित किए बिना, हमें यह मान लेना चाहिए कि यह सबसे अच्छा काम करने वाले ऑप्टिमाइज़र पर निर्भर है।
मन्नंगो

9

Existsकीवर्ड सही या गलत का मूल्यांकन करता है, लेकिन INकीवर्ड इसी उप क्वेरी स्तंभ में सभी मूल्य की तुलना करें। एक और एक कमांड के Select 1साथ उपयोग किया जा सकता है Exists। उदाहरण:

SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...)

लेकिन INइतनी Existsतेजी से कम कुशल है ।


5

मुझे लगता है,

  • EXISTSजब आपको किसी अन्य सबक्वेरी के साथ क्वेरी के परिणामों का मिलान करने की आवश्यकता होती है। सब # 1 परिणामों को पुनः प्राप्त करने की आवश्यकता है, जहां SubQuery परिणाम मेल खाते हैं। एक तरह की ज्वाइन .. जैसे कि कस्टमर टेबल # 1 का चयन करें जिन्होंने ऑर्डर टेबल # 2 भी रखा हो

  • यदि किसी विशिष्ट कॉलम का मूल्य INएक सूची (1,2,3,4,5) है, तो उन ग्राहकों को पुनः प्राप्त करना है, जो निम्नलिखित zipcodes यानी zip_code मानों में निहित ग्राहकों का चयन करते हैं (....) सूची में।

जब एक दूसरे का उपयोग करने के लिए ... जब आपको लगता है कि यह उचित रूप से पढ़ता है (बेहतर इरादे संचार करता है)।


4

अंतर यहाँ है:

select * 
from abcTable
where exists (select null)

उपरोक्त क्वेरी सभी अभिलेखों को वापस कर देगी, जबकि नीचे एक खाली आएगा।

select *
from abcTable
where abcTable_ID in (select null)

इसे आज़माएं और आउटपुट देखें।


1
हम्म ... त्रुटि: [SQL0104] टोकन) मान्य नहीं था। दोनों मामलों में। क्या आप एक विशेष RDBMS मान रहे हैं?
jmarkmurphy

3

मेरे ज्ञान के अनुसार जब एक उपकुंजी एक NULLमूल्य देता है तो पूरा विवरण बन जाता है NULL। उस स्थिति में हम EXITSकीवर्ड का उपयोग कर रहे हैं । यदि हम उप-वर्गों में विशेष मूल्यों की तुलना करना चाहते हैं तो हम INकीवर्ड का उपयोग कर रहे हैं ।


3

कौन सा तेज़ है यह आंतरिक क्वेरी द्वारा प्राप्त प्रश्नों की संख्या पर निर्भर करता है:

  • जब आपकी आंतरिक क्वेरी में पंक्तियों की संख्या हजार हो जाती है, तो EXIST बेहतर विकल्प होगा
  • जब आपकी आंतरिक क्वेरी कुछ पंक्तियों को ला रही है, तो IN तेज हो जाएगा

सही या गलत पर मूल्यांकन का मूल्यांकन करें, लेकिन कई मूल्य की तुलना करें। जब आप नहीं जानते कि रिकॉर्ड मौजूद है या नहीं, तो आपको EXIST चुनना चाहिए


3

कारण यह है कि EXISTS ऑपरेटर "कम से कम पाया गया" सिद्धांत के आधार पर काम करता है। यह सच हो जाता है और कम से कम एक मिलान पंक्ति मिल जाने के बाद स्कैनिंग टेबल बंद हो जाती है।

दूसरी ओर, जब IN ऑपरेटर को एक सबक्वेरी के साथ जोड़ा जाता है, तो MySQL को पहले सबक्वेरी को प्रोसेस करना होगा, और फिर सब क्वेरी को प्रोसेस करने के लिए सबक्वेरी के परिणाम का उपयोग करना होगा।

अंगूठे का सामान्य नियम यह है कि यदि उपकुंजी में बड़ी मात्रा में डेटा होता है, तो EXISTS ऑपरेटर एक बेहतर प्रदर्शन प्रदान करता है।

हालाँकि, IN ऑपरेटर का उपयोग करने वाली क्वेरी तेजी से प्रदर्शन करेगी यदि उप-सेट से लौटाया गया परिणाम बहुत छोटा है।


1

मेरी समझ यह है कि दोनों को तब तक एक जैसा होना चाहिए जब तक हम NULL मानों के साथ काम नहीं कर रहे हैं।

उसी कारण से जो क्वेरी = NULL vs NULL के लिए मान नहीं लौटाता है। http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/

जैसा कि बूलियन बनाम तुलनित्र तर्क के लिए जाता है, एक बूलियन उत्पन्न करने के लिए दोनों मूल्यों की तुलना करने की आवश्यकता होती है और यह है कि यदि कोई शर्त काम करता है।



0

यदि एक सबक्वेरी एक से अधिक मान लौटाता है, तो आपको बाहरी क्वेरी निष्पादित करने की आवश्यकता हो सकती है- यदि शर्त में निर्दिष्ट कॉलम के भीतर सबक्वेरी के परिणाम सेट में किसी भी मूल्य से मेल खाता है। इस कार्य को करने के लिए, आपको inकीवर्ड का उपयोग करने की आवश्यकता है ।

रिकॉर्ड्स का एक सेट मौजूद है या नहीं यह जांचने के लिए आप एक सबक्वेरी का उपयोग कर सकते हैं। इसके लिए, आपको existsउप-वर्ग के साथ खंड का उपयोग करने की आवश्यकता है । existsकीवर्ड हमेशा सही या गलत मान।


0

मेरा मानना ​​है कि इसका सीधा जवाब है। आप उन लोगों से इसकी जांच क्यों नहीं करते हैं जिन्होंने अपने सिस्टम में उस फ़ंक्शन को विकसित किया है?

यदि आप एक MS SQL डेवलपर हैं, तो इसका जवाब सीधे Microsoft से है।

IN:

निर्धारित करता है कि क्या एक निर्दिष्ट मूल्य किसी उपश्रेणी या सूची में किसी भी मूल्य से मेल खाता है।

EXISTS:

पंक्तियों के अस्तित्व के परीक्षण के लिए एक उपश्रेणी निर्दिष्ट करता है।


0

मैंने पाया कि EXISTS कीवर्ड का उपयोग करना वास्तव में बहुत धीमा है (यह Microsoft Access में बहुत सही है)। इसके बजाय मैं इस तरह से जुड़ने वाले ऑपरेटर का उपयोग करता हूं: चाहिए-आई-यू-ए-कीवर्ड-मौजूद-इन-एसक्यूएल


-1

EXISTS प्रदर्शन की तुलना में तेज़ है। यदि फ़िल्टर मानदंड में से अधिकांश सबक्वेरी में है तो IN का उपयोग करना बेहतर है और यदि अधिकांश फ़िल्टर मापदंड मुख्य क्वेरी में हैं तो EXISTS का उपयोग करना बेहतर है।


यह दावा वास्तव में किसी भी सबूत से समर्थित नहीं है, क्या यह है?
लुकास एडर

-2

यदि आप IN ऑपरेटर का उपयोग कर रहे हैं, तो SQL इंजन आंतरिक क्वेरी से प्राप्त सभी रिकॉर्ड स्कैन करेगा। दूसरी ओर यदि हम EXISTS का उपयोग कर रहे हैं, तो SQL इंजन मैच मिलते ही स्कैनिंग प्रक्रिया को रोक देगा।


@ जिगी समझा? यह बहुत ज्यादा है जो स्वीकृत उत्तर भी कहता है। MUST में हर एक रिकॉर्ड की जाँच करें, जैसे ही यह पता चलता है, यह मौजूद हो सकता है।
बेन थर्ले

नहीं, सही नहीं है। INऔर EXISTSसमतुल्य हो सकते हैं और एक दूसरे में बदल सकते हैं।
लुकास एडर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.