2010-02-11 28 views
8

Çalışması gerektiğini düşündüğüm bir sorgu almakta sorun yaşıyorum. Bu formdamysql SELECT NOT IN() - bağlantı kümesi mi?

SELECT DISTINCT a, b, c FROM t1 WHERE NOT IN (SELECT DISTINCT a,b,c FROM t2) AS alias 

öyle Ama MySQL bobinleri burada "IN (" başlar. Does MySQL desteği bu sözdizimi? Ben bu sonuçları alma hakkında gitmek nasıl? I (a, b farklı dizilerini bulmak istediğiniz Değilse c) Tablo 2'de bulunmayan tablo 1'de.

cevap

12

SELECT DISTINCT a, b, c FROM t1 WHERE NOT EXISTS (SELECT NULL FROM t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) 

dEĞİL İÇİNDE kullanarak yalnızca bir anahtarı kontrol bile, bunu yapmanın en iyi yöntem değildir: sen var kullanmalıdır. Bunun nedeni, DEĞİŞTİRMEYİ kullanmazsanız, DBMS'nin yalnızca gerekli sütunlar için indeksler varsa indeksleri kontrol etmesi yeterli olacaktır. Burada, NOT IN için gerçek verileri okumak ve daha sonra kontrol edilmesi gereken bir tam sonuç kümesi oluşturmak zorunda kalacaksınız. .

LEFT JOIN kullanma ve sonra NULL'u kontrol etme de kötü bir fikirdir, tabloların tüm birleştirmeyi yapması gerektiğinden, tabloların büyük olması nedeniyle ağrısal olarak yavaş olacaktır, her iki tablonun tamamını okumalı ve sonradan bir çok şeyi atmalıdır. o. Ayrıca, sütunlar NULL için NULL değerleri için izin verirse, yanlış pozitif bildirir.

+0

Biliyor musun? Bu sorguyu çalıştırdım ve uzun bir zaman alıyordu (10 dakikadan uzun), bu yüzden onu öldürdüm. Sonra iki tablo için temp tabloları oluşturdum ve farklı bilgiler ekledim. Ardından geçici tablolara karşı sorguyu çalıştırdım. Bir dakika ve 4 saniye sürdü. Neden bu sorguyu mysql bu şekilde optimize edemedi? – user151841

+1

Dürüst olmak gerekirse, mysql bazı konularda oldukça aptal ve yavaştır. Oracle, MS SQL ve PostgreSQL birçok açıdan çok daha iyi. Tabii ki, eğer tabloları zaten yoksa, tabloların sütunlarına indeksler eklerseniz çok daha hızlı olacaktır. Bu, indekslerin her seferinde güncellenmesi gerektiğinden, ekleme zamanı maliyetine katlanmasına rağmen, her bir işlemin kaç kez yapıldığını ve daha fazla zaman kritik olan bir meseledir. – wich

0

Bildiğim kadarıyla, NOT IN sadece bir seferde 1 alan için kullanılabilir ve alan "WHERE" arasında belirtilmelidir. ve "dEĞİL İÇİNDE"

(Düzenleme :) bir NOT EXISTS kullanmayı deneyin.

SELECT a, b, c 
FROM t1 
WHERE NOT EXISTS 
    (SELECT * 
    FROM t2 
    WHERE t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) 

Ayrıca, eşit olan a, b ve c'deki bir içsel birleşmenin tümü, DISTINCINCT'lerin tümünü vermezken, WHERE IS NULL deyimine sahip bir SOL JOIN, size aşağıda belirtildiği gibi, DISTINCT olanları vermelidir.

+0

http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html Kutsal Tanrı itibaren

, bu bir kabus sorgusu yapar. Sadece diğer ikisinin değerlerine bağlı olarak a, b veya c değerlerini önemsiyorum! – user151841

+0

Birleştirme nasıl kullanılır? 3 alanın hepsine içsel olarak katılma, tüm ayrık olmayan tupller – froadie

+0

'u iade etmeli mi? A, b, c SEÇİLMEDEN T1 TARAFINDAN SEÇİN (SELECT * SELECT * t2 WHERE t1.a = t2.a VE t1.b = t2.b VE t1.c = t2.c). Bunun tam olarak doğru olup olmadığından emin değilim, şu anda çok fazla deneyime sahip değildim – froadie

0

DISTINCT t1 SEÇ. * T1 SOLDAN T2 JOIN (t1.a = t2.a VE t1.b = t2.b VE t1.c = t2.c) t2.a IS NULL NEREDE

+0

Bu çok kötü bir fikir, eğer masalar çok büyükse, birleşme çok yavaş olacaktır. Bir sürü iş yapıyorsunuz, her iki tabloya da tam olarak sol bir sonuç kümesi oluşturuyorsunuz. – wich

+0

Gerçekten. Performans bilge değil. – Charles

-1

WHERE maddesinden sonra bir sütun listesi eklemeniz ve diğer adı KALDIRIN.

Bunu benzer bir tabloyla test ettim ve çalışıyor. MySQL world db kullanarak

SELECT DISTINCT a, b, c 
FROM t1 WHERE (a,b,c) 
NOT IN (SELECT DISTINCT a,b,c FROM t2) 

:

-- dont include city 1, 2 
SELECT DISTINCT id, name FROM city 
WHERE (id, name) 
NOT IN (SELECT id, name FROM city WHERE ID IN (1,2)) 
+0

NOT EXISTS kullanmak daha iyi olurdu, IN, tüm tabloyu okuyarak alt sorgu için bir sonuç kümesini oluşturmaya zorlar, DEĞİŞTİRME kullanılmazsa, alt sorgu için sonuç kümesi oluşturulmalı ve sütunlar varsa indekslenir, DEĞİLDİR DEĞİL sadece endeksleri okuyacaktır. – wich

+0

Bundan emin misin? Sütunlar endekslenmemişse VARSAYILANLARDA yavaş DEĞİL DEĞİLDİR. – Yada

0

Eh, tüm büyük tavsiye başkalarının rağmen, benim kendi soruya cevap verdi gidiyorum.

Yapmaya çalıştığım şeyin düzgün sözdizimi. Değil, "Nasıl Belirli bir sonuç kümesi alırım" "Nasıl SQL bu düşünceyi ifade etmeyin"

SELECT DISTINCT a, b, c FROM t1 WHERE (a,b,c) NOT IN (SELECT DISTINCT a,b,c FROM t2) 

bunun verimlilik için kefil olamaz, ama örtük koyuyordum geniş soruları oldu. Biliyorum bu, bıçaklayan herkese haksızlık, üzgünüm!

+1

t2'nin a, b ve c sütunlarının tanımına bağlı olarak bu yanlış olabilir! NULL değerlerine izin verirlerse, NOT IN için sonuç böyle bir değer için her zaman bilinmeyecektir. DEĞİLDİR * * * bunu ifade etmenin doğru yolu, bunun için EXISTS yaratılmadı. – wich

+0

Harika! Teşekkürler. – user151841

3

Sağlanan yanıtlarla bile bu sorguyu yürütmenin doğru yolunu bulmakta zorluk çekiyordum; o zaman ben gerekli MySQL belgelerine referans buldum:

SELECT DISTINCT store_type FROM stores WHERE NOT EXISTS (SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);

Etrafa alt sorgunun içindeki ilk sorgudan 'mağazaların tabloya referans kullanıyordu Beynimi sarmak zorunda numara. Umarım bu yardımcı olur (bu eski bir iplik olduğu için, ya da başkalarını yardımcı olur.)