एसक्यूएल - एक टेबल से रिकॉर्ड पाते हैं जो दूसरे में मौजूद नहीं है


310

मुझे निम्नलिखित दो SQL टेबल (MySQL में) मिली हैं:

Phone_book
+----+------+--------------+
| id | name | phone_number |
+----+------+--------------+
| 1  | John | 111111111111 |
+----+------+--------------+
| 2  | Jane | 222222222222 |
+----+------+--------------+

Call
+----+------+--------------+
| id | date | phone_number |
+----+------+--------------+
| 1  | 0945 | 111111111111 |
+----+------+--------------+
| 2  | 0950 | 222222222222 |
+----+------+--------------+
| 3  | 1045 | 333333333333 |
+----+------+--------------+

मुझे कैसे पता चलेगा कि कौन से कॉल उन लोगों द्वारा किए गए थे जो अंदर phone_numberनहीं हैं Phone_book? वांछित उत्पादन होगा:

Call
+----+------+--------------+
| id | date | phone_number |
+----+------+--------------+
| 3  | 1045 | 333333333333 |
+----+------+--------------+

कोई भी सहायताकाफी प्रशंसनीय होगी।

जवाबों:


438

अलग-अलग दक्षता के साथ ऐसा करने के कई तरीके हैं, यह इस बात पर निर्भर करता है कि आपका क्वेरी ऑप्टिमाइज़र कितना अच्छा है, और आपके दो आकारों का सापेक्ष आकार:

यह सबसे छोटा कथन है, और अगर आपकी फोन बुक बहुत कम है, तो यह सबसे जल्दी हो सकता है:

SELECT  *
FROM    Call
WHERE   phone_number NOT IN (SELECT phone_number FROM Phone_book)

वैकल्पिक रूप से ( Alterlife के लिए धन्यवाद )

SELECT *
FROM   Call
WHERE  NOT EXISTS
  (SELECT *
   FROM   Phone_book
   WHERE  Phone_book.phone_number = Call.phone_number)

या (WOPR के लिए धन्यवाद)

SELECT * 
FROM   Call
LEFT OUTER JOIN Phone_Book
  ON (Call.phone_number = Phone_book.phone_number)
  WHERE Phone_book.phone_number IS NULL

(इसे अनदेखा करते हुए, जैसा कि दूसरों ने कहा है, यह सामान्य रूप से आपके द्वारा इच्छित कॉलमों का चयन करने के लिए सबसे अच्छा है, ' *')


1
IN से बचें, EXISTS का उपयोग करें - संकेत प्रश्न शीर्षक में है
annakata

28
बाईं बाहरी जुड़ाव संभवतः सामान्य मामले में सबसे तेज है क्योंकि यह सबक्वेरी के बार-बार निष्पादन को रोकता है।
डब्ल्यूओपीआर

Picky नहीं होना चाहिए, लेकिन मेरे सुझाव पर उपशब्‍द रिटर्न <code> 'x' </ code> चुनें और <code> select * </ code>
Alterlife

हाँ - MySQL मैनुअल से पता चलता है कि यह 'EXISTS' क्वेरी के लिए सामान्य है
Alnitak

2
@Alnitak: दूसरी क्वेरी में आपको SELECT *सबक्वेरी की आवश्यकता नहीं है । इसके बजाय, उदाहरण के लिए, SELECT 1बहुत सुंदर होना चाहिए।
अलेक्जेंडर अबाकुमोव

90
SELECT Call.ID, Call.date, Call.phone_number 
FROM Call 
LEFT OUTER JOIN Phone_Book 
  ON (Call.phone_number=Phone_book.phone_number) 
  WHERE Phone_book.phone_number IS NULL

सबक्वेरी को हटा देना चाहिए, जिससे क्वेरी ऑप्टिमाइज़र को अपना जादू चलाने में मदद मिल सके।

इसके अलावा, "SELECT *" से बचें क्योंकि यह आपके कोड को तोड़ सकता है यदि कोई अंतर्निहित तालिका या विचार को बदल देता है (और यह अक्षम है)।


10
यह आम तौर पर सबसे कुशल तरीका है क्योंकि यह दूसरी मेज पर कई पास नहीं करता है ... उम्मीद है कि कुछ लोग कॉमेन्ट पढ़ रहे होंगे।
नेरडफेस्ट

3
मैं उम्मीद करूंगा कि लोग प्रोफ़ाइल करें: जब तक आप एक शीर्ष एसक्यूएल प्रदर्शन गुरु नहीं होते हैं, पहले से बता देना कि सबसे तेज़ क्या होगा, काफी मुश्किल है (और आपके द्वारा उपयोग किए जाने वाले डीबीएमएस इंजन पर निर्भर करता है)।
bortzmeyer

2
बिग ओ नोटेशन आपको आसानी से बताएगा कि आप इस मामले में सबसे तेज़ होने की क्या उम्मीद कर सकते हैं। यह भिन्नता के आदेश हैं।
जोन्सपोलिस

देखें Afterlife के जवाब अगर वहाँ एक है, वहाँ और मेरी टिप्पणी 1:Nअपने दो तालिकाओं के बीच संबंध। या DISTINCTजैसा कि व्लादो के जवाब
टूलमेकरसेव

25

नीचे दिए गए कोड बड़े डेटासेट के साथ काम करते समय ऊपर दिए गए उत्तरों की तुलना में थोड़ा अधिक कुशल होंगे।

SELECT * FROM Call WHERE 
NOT EXISTS (SELECT 'x' FROM Phone_book where 
Phone_book.phone_number = Call.phone_number)

1
हमेशा की तरह, यह सबसे अच्छा प्रदर्शन वाले को चुनने के लिए अपने लक्ष्य डेटासेट के खिलाफ प्रश्नों के प्रदर्शन की रूपरेखा तैयार करने के लायक है। SQL ऑप्टिमाइज़र इन दिनों काफी अच्छे हैं कि प्रदर्शन के परिणाम अक्सर आश्चर्यजनक होते हैं।
ग्रेग हेवगिल

1
इस दृष्टिकोण का एक लाभ (WOPR द्वारा बनाम बाईं ओर) यह है कि Callअगर इसमें कई मिलान पंक्तियाँ हैं, तो यह प्रति पंक्ति की कई पंक्तियों को वापस करने से बचती है Phone_book। यही है, अगर 1:Nआपके दो तालिकाओं के बीच एक संबंध है।
टूलमेकरसेव

मैं इस एक के साथ शुरू होगा - यह सीधे इरादे का प्रतिनिधित्व करता है। यदि प्रदर्शन पर्याप्त अच्छा नहीं है, तो सुनिश्चित करें कि उपयुक्त इंडेक्स मौजूद हैं। तभी, कम-स्पष्ट प्रयास करें LEFT OUTER JOIN, देखें कि क्या इसका प्रदर्शन बेहतर है।
टूलमेकरसेव

6
SELECT DISTINCT Call.id 
FROM Call 
LEFT OUTER JOIN Phone_book USING (id) 
WHERE Phone_book.id IS NULL

यह आपकी Phone_book तालिका में मौजूद अतिरिक्त id-s को लौटा देगा।


4

मुझे लगता है

SELECT CALL.* FROM CALL LEFT JOIN Phone_book ON 
CALL.id = Phone_book.id WHERE Phone_book.name IS NULL

idमें स्तंभ callतालिका के रूप में एक ही मूल्य नहीं है idमें स्तंभ Phone_bookताकि आप इन मूल्यों पर शामिल नहीं हो सकते, टेबल। एक समान दृष्टिकोण के लिए WOPR का उत्तर देखें।
माइकल फ्रेड्रिकसन

3
SELECT t1.ColumnID,
CASE 
    WHEN NOT EXISTS( SELECT t2.FieldText  
                     FROM Table t2 
                     WHERE t2.ColumnID = t1.ColumnID) 
    THEN t1.FieldText
    ELSE t2.FieldText
END FieldText       
FROM Table1 t1, Table2 t2

यदि एक ही कॉलम के लिए डेटा किसी अन्य तालिका में मौजूद नहीं है, तो यह आपको एक तालिका से डेटा लौटाएगा
हरविंदर सिद्धू

1
SELECT name, phone_number FROM Call a
WHERE a.phone_number NOT IN (SELECT b.phone_number FROM Phone_book b)

यह प्रश्न का उत्तर प्रदान नहीं करता है। किसी लेखक से स्पष्टीकरण मांगने या उसका अनुरोध करने के लिए, उनके पोस्ट के नीचे एक टिप्पणी छोड़ दें। - समीक्षा से
डेनिस क्रिचेल

@DennisKriechel ने क्वेरी को अपडेट किया ताकि यह प्रश्न के लिए अधिक विशिष्ट हो।
यहोशिएट्स

1

वैकल्पिक रूप से,

select id from call
minus
select id from phone_number

1
सुनिश्चित नहीं है कि यह सवाल का जवाब है (हालांकि MINUS) ऑपरेटर एक नया अतिरिक्त है। यह निम्न गुणवत्ता कतार में समाप्त हुआ - आप इस उत्तर को बढ़ाना पसंद कर सकते हैं।
-फू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.