Bir tabloda başka bir tabloda bulunmayan tüm kayıtlar nasıl seçilir?


471

table1 (kimlik, ad)
table2 (kimlik, ad)

Sorgu:

SELECT name   
FROM table2  
-- that are not in table1 already

Yanıtlar:


846
SELECT t1.name
FROM table1 t1
LEFT JOIN table2 t2 ON t2.name = t1.name
WHERE t2.name IS NULL

S : Burada neler oluyor?

C : Kavramsal olarak, tüm satırları seçiyoruz table1ve her satır table2için namesütun için aynı değere sahip bir satır bulmaya çalışıyoruz . Böyle bir satır yoksa, table2sonucumuzun kısmını o satır için boş bırakırız . Ardından, sonuçta yalnızca eşleşen satırın bulunmadığı satırları seçerek seçimimizi kısıtlarız. Son olarak, namesütun ( sonuçta olduğundan emin olduğumuz alan hariç) sonucumuzdaki tüm alanları yok sayıyoruz table1.

Her durumda mümkün olan en performanslı yöntem olmasa da, ANSI 92 SQL'i uygulamaya çalışan her veritabanı motorunda çalışmalıdır.


16
@ z-boss: Aynı zamanda SQL Server'da en az performans sergileyen: explainextended.com/2009/09/15/…
OMG Ponies

7
@BunkerBoy: Sol birleşim, sağdaki satırların, soldaki satırların eklenmesini etkilemeden var olmamasına izin verir. Bir iç birleşim, sol ve sağdaki satırların mevcut olmasını gerektirir. Burada yaptığım temelde bir iç birleştirme ters seçim almak için bazı mantık uygulamaktır.
Kris

2
Bu çok kolay görselleştirmeye yardımcı oldu, diğerleri 5 farklı yol gibi koydu ama bu yardımcı oldu. basit: önce sola katılmaya başlarsınız, A'daki her şey ve B'deki A ile eşleşen her şey. Sonra söyle, tamam ben sadece boş olmak istiyorum. Bu şekilde A da B'de bir maç bulunmayan tüm satırlarınız var
Muhammed Umer

7
Bu çözümlerin (kabul edilen ve oylanan) tek çözüm olduğuna dikkat edilmelidir ki bence birden fazla alanın devreye girdiği bir senaryo için düzenlenebilir. Özellikle, alan reklam alanı2 kombinasyonunun ikinci tabloda olmadığı tablodan alan, alan 2, alan 3'ü döndürüyorum. Bu cevaptaki
katılımı değiştirmek dışında

1
Sadece "AND t2.name IS NULL" değil, "WHERE t2.name IS NULL" kullandığınızdan emin olun, çünkü "ve" doğru sonuçlar vermeyecektir. Nedenini gerçekten anlamıyorum ama bu bir gerçek, test ettim.
user890332

236

Ya yapabilirsin

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT name 
     FROM table1)

veya

SELECT name 
FROM table2 
WHERE NOT EXISTS 
    (SELECT * 
     FROM table1 
     WHERE table1.name = table2.name)

Bunu başarmak için 3 teknik için bu soruya bakın


38
Bu, büyük miktarda veriyle inanılmaz derecede yavaştır.
Lightbulb1

Evet, gerçekten çok yavaş
sirus

Var olmayan sorgunun alt sorgusunda "from table1" olmamalıdır.
Hound

Bunun nasıl bu kadar çok oy aldığını çok karıştı. Kabaca aynı sayıda tuş vuruşuyla inanılmaz derecede daha hızlı olan bu soruna bir yaklaşım olduğunda, bunu kullanmak için bir neden düşünmek çok zor buluyorum.
searchengine27

Bu benim için çalıştı .. Teşekkürler
Thameem

81

2. cevabı oylayacak yeterli temsil puanım yok. Ama en üstteki cevaba yapılan yorumlara katılmıyorum. İkinci cevap:

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT name 
     FROM table1)

Uygulamada FAR daha verimlidir. Nedenini bilmiyorum, ama 800k + kayıtlara karşı çalıştırıyorum ve fark yukarıda yayınlanan 2. cevaba verilen avantaj ile çok büyük. Sadece benim 0.02 $


31
NOT IN sorgusunda alt sorgu yalnızca bir kez gerçekleştirilir, EXISTS sorgusunda alt sıra her satır için gerçekleştirilir
Carrick

2
sen müthiş :) bu şekilde 25 saniye sorgu sol birleşimi kullanarak sadece 0,1 sn dönüştürmek
Bassem Shahin

3
cevaplar belirli bir sıraya göre değildir, bu nedenle ikinci cevap ne demek istediğinizi ifade etmez.

38

Bu, minusoperasyonla elde edebileceğiniz saf set teorisidir .

select id, name from table1
minus
select id, name from table2

Sizce bu sola katılmaktan çok daha verimli mi?
uhs

Olmalı. Eksi komutu bu durum için tasarlanmıştır. Elbette herhangi bir veri setini değerlendirmenin tek yolu, her iki şekilde de denemek ve hangisinin daha hızlı çalıştığını görmektir.
Kış

9
T-SQL'de, set operatörü "hariç" tir. Bu benim için çok uygun ve herhangi bir yavaşlamaya neden olmadı.

2
SQLite'de "eksi" işleci de "hariç" tir.
lifjoy

MySQL, MINUS operatörünü desteklemez.
Muhammad Azeem


16

Tuzaklara dikkat edin. Alan Eğer Nameiçinde Table1Boşlara ihtiva Sürprizlerle demektir. Daha iyisi:

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT ISNULL(name ,'')
     FROM table1)

1
COALESCE> ISNULL (ISNULL, COALESCE'den yeni veya daha iyi bir şey yapmayan dile işe yaramaz bir T-SQL ekidir)
Kris

14

İşte benim için en iyi olan şey.

SELECT *
FROM @T1
EXCEPT
SELECT a.*
FROM @T1 a
JOIN @T2 b ON a.ID = b.ID

Bu, denediğim diğer yöntemlerden iki kat daha hızlıydı.


Teşekkürler, bu çok büyük miktarda Veri ile iyi çalışır! Ama sadece 'Hariç' terimini merak ediyorum.
PatsonLeaner


7

Bu benim için keskin çalışıyor

SELECT * 
FROM [dbo].[table1] t1
LEFT JOIN [dbo].[table2] t2 ON t1.[t1_ID] = t2.[t2_ID]
WHERE t2.[t2_ID] IS NULL

1

Sorguya bakın:

SELECT * FROM Table1 WHERE
id NOT IN (SELECT 
        e.id
    FROM
        Table1 e
            INNER JOIN
        Table2 s ON e.id = s.id);

Kavramsal olarak: Alt sorguda ve ardından ana sorguda alt sorguda olmayan kayıtları getirerek eşleşen kayıtları getirme.


0

(Ben henüz yorum yapmak için yeterince serin değilim) repost gidiyorum doğru durumda .... başka kimse daha iyi açıklanması gerektiğini düşündüm durumunda.

SELECT temp_table_1.name
FROM original_table_1 temp_table_1
LEFT JOIN original_table_2 temp_table_2 ON temp_table_2.name = temp_table_1.name
WHERE temp_table_2.name IS NULL

Ve mySQL tablo adları arasında virgül gerektiren FROM sözdizimi gördüm ama sqlLite alan tercih gibi görünüyordu.

Sonuçta, değişken değişken isimlerini kullandığınızda soru bırakıyor. Değişkenlerim daha anlamlı olmalı. Ve birisi neden virgül kullanmamız gerektiğini veya virgül kullanmamamızı açıklamalıdır.


0

Belirli bir kullanıcıyı seçmek istiyorsanız

SELECT tent_nmr FROM Statio_Tentative_Mstr
WHERE tent_npk = '90009'
AND
tent_nmr NOT IN (SELECT permintaan_tent FROM Statio_Permintaan_Mstr)

tent_npkBir kullanıcının bir birincil anahtar

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.