2009-08-17 22 views
11

Bir alt sorgu tarafından değiştirilmiş sonuçları döndüren bir SQL deyimi veya geri dönmeye çalıştığınız bilgilerle ilgilenen bir katılım veya başka bir şey nasıl yapılır? ÖrneğinSQL: * Farklı * satırların değerlerine göre satırları seçmek için "DEĞİL" seçeneği?

:

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'); 

Yani homer Takımına karar veremez, bu yüzden hem var:

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

Birisi yanlış birden fazla takımda olabilir. Do'h!

pin pals takımında olmayan herkesi tanımak istiyorum the homer team. Yapabileceğim en iyi şudur:

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'); 

sonuçlanan: Bildiğiniz,

+-----------------------+----------------+ 
| 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) 

, parlak!

alt sorgu B, birkaç satır D. Büyük A ila yüzbinlerce için oldukça kötü, sorgu her sonucu aday olacak gibi performans, yaşayacaktır satırlar.

Daha iyi bir yol nedir? Çoğunlukla kendi kendine bir katılımın hile yapacağını düşünüyordum, ama kafamı bunun üzerine nasıl yapacağım.

kullanmadan, bunu yapmak için başka yolları var mı, NOT IN(SELECT ...) Ayrıca

, sorunun bu tip adı nedir?

+1

sol dıştan içe kendinize ait olanı istediğiniz şeydir. –

cevap

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; 

Böyle bunu da yapabilirsiniz: Bu arada

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 
    ); 

, bu bir "Sol Karşıtı Yarı Üyelik" denir.

+0

Brilliant! İlk örneğiniz kesinlikle benim sorunum için bir gelişmedir. Hala biraz yavaş çalışıyor (MySQL sürüm 5.0.37) ama birkaç ... iyi, en azından şimdi geri geliyor! Bunu açıklayan terim için teşekkürler (Left Anti-Semi Join) –

2

LEFT JOIN ve birleşik tablonun içinde hiçbir veri bulunmadığından emin olun (her şey null). Bunun gibi

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

Bu kesinlikle çalışır, ancak alt sorgularından daha mı yoksa daha az mı etkilidir? Birliğe daha fazla dayanacakmış gibi görünüyor ama bilmiyorum. – chrissr

+0

Tablo yapısına, hangi dizinlerin kullanılabileceğine, tablodaki satır sayısına, vb., A takımında veya takım B'de kaç kişinin olduğu vb. Çok bağımlıdır. –

İlgili konular