2009-08-17 7 views
11

आप एक SQL कथन कैसे बनाते हैं जो एक सबक्वायरी द्वारा संशोधित परिणाम लौटाता है, या कोई अन्य - या कुछ और, जो उस जानकारी से संबंधित है जो आप लौटने की कोशिश कर रहे हैं?एसक्यूएल: * अलग * पंक्तियों के मूल्यों के आधार पर पंक्तियों का चयन करने के लिए "नहीं" विकल्प?

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

CREATE TABLE bowlers (
bowling_id int4 not null primary key auto_increment, 
name text, 
team text 
); 

किसी ने गलत तरीके से एक से अधिक टीम पर हो सकता है:

INSERT INTO `bowlers` (`name`, `team`) VALUES 
('homer', 'pin pals'), 
('moe', 'pin pals'), 
('carl', 'pin pals'), 
('lenny', 'pin pals'), 
('homer', 'The homer team'), 
('bart', 'The homer team'), 
('maggie', 'The homer team'), 
('lisa', 'The homer team'), 
('marge', 'The homer team'), 
('that weird french guy', 'The homer team'); 

तो homer उनकी टीम पर तय नहीं कर सकता, तो वह दोनों पर है। Do'h!

मैं the homer team पर मौजूद सभी लोगों को जानना चाहता हूं जो pin pals टीम पर भी नहीं हैं।

+-----------------------+----------------+ 
| name     | team   | 
+-----------------------+----------------+ 
| bart     | The homer team | 
| maggie    | The homer team | 
| lisa     | The homer team | 
| marge     | The homer team | 
| that weird french guy | The homer team | 
+-----------------------+----------------+ 
5 rows in set (0.00 sec) 

कौन सा, तुम्हें पता है, शानदार: सबसे अच्छा मैं कर सकता हूँ यह है:

SELECT a.name, a.team 
    FROM bowlers a where a.team = 'The homer team' 
    AND a.name 
    NOT IN (SELECT b.name FROM bowlers b WHERE b.team = 'pin pals'); 

में परिणामस्वरूप!

प्रदर्शन, के रूप में भुगतना होगा सबक्वेरी क्वेरी, जो बी में कुछ पंक्तियों के लिए डी ग्रेट के लिए एक के लिए है, सैकड़ों हजारों के लिए बहुत बुरा की प्रत्येक परिणाम के लिए चलाया जा रहा है पंक्तियों।

बेहतर तरीका क्या है? मैं ज्यादातर सोच रहा हूं कि एक आत्म चाल चलाना होगा, लेकिन मैं अपने सिर को लपेट नहीं सकता कि यह कैसे करें।

वहाँ का उपयोग किए बिना ऐसा करने के लिए, किसी भी अन्य तरीके हैं, NOT IN(SELECT ...)

इसके अलावा, क्या इस प्रकार की समस्या के लिए नाम क्या है?

+1

बाएं बाहरी वापस अपने आप में शामिल होना चाहते हैं जो आप चाहते हैं। –

उत्तर

15
इस तरह

:

SELECT a.name, a.team 
FROM bowlers a 
LEFT OUTER JOIN bowlers b ON a.name = b.name AND b.team = 'pin pals' 
WHERE a.team = 'The homer team' 
AND b.name IS NULL; 

आप इसे इस तरह भी कर सकते हैं:

SELECT a.name, a.team 
FROM bowlers a 
WHERE a.team = 'The homer team' 
AND NOT EXISTS (SELECT * FROM bowlers b 
    WHERE b.team = 'pin pals' 
    AND a.name = b.name 
    ); 

वैसे, कहा जाता है एक "वाम विरोधी अर्ध में शामिल हों"।

+0

शानदार! आपका पहला उदाहरण निश्चित रूप से मेरी समस्या में सुधार है। अभी भी थोड़ा धीमा चल रहा है (MySQL संस्करण 5.0.37) लेकिन कुछ ... अच्छा, कम से कम अब यह वापस आ रहा है! इस शब्द को समझाने के लिए धन्यवाद (बाएं एंटी-सेमी जॉइन) –

2

आप LEFT JOIN कर सकते हैं और यह सुनिश्चित कर सकते हैं कि इसमें शामिल तालिका में कोई डेटा नहीं है (सब कुछ शून्य है)।

SELECT a.name, a.team 
    FROM bowlers a 
    LEFT JOIN bowlers b 
     ON b.name = a.name AND b.team = 'pin pals' 
    WHERE a.team = 'The homer team' 
    AND a.name 
    -- the join has to fail for this to be null 
    AND b.bowling_id IS NULL 
+0

यह निश्चित रूप से काम करता है, लेकिन क्या यह अपने सबक्वायरी से कम या कम कुशल है? ऐसा लगता है कि इसमें शामिल होने पर अधिक ओवरहेड होगा, लेकिन मुझे नहीं पता। – chrissr

+0

यह तालिका संरचना पर निर्भर है, कौन सी इंडेक्स उपलब्ध हैं, तालिका में पंक्तियों की संख्या इत्यादि, टीम ए या टीम बी आदि में कितने लोग हैं –