Bagaimana cara memilih semua catatan dari satu tabel yang tidak ada di tabel lain?

469

table1 (id, name)
table2 (id, name)

Pertanyaan:

SELECT name   
FROM table2  
-- that are not in table1 already
bos-z
sumber

Jawaban:

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

T : Apa yang terjadi di sini?

A : Secara konseptual, kami memilih semua baris dari table1dan untuk setiap baris kami berusaha menemukan baris table2dengan nilai yang sama untuk namekolom. Jika tidak ada baris seperti itu, kami hanya membiarkan table2bagian dari hasil kami kosong untuk baris itu. Kemudian kami membatasi pilihan kami dengan memilih hanya baris-baris di hasil di mana baris yang cocok tidak ada. Akhirnya, Kami mengabaikan semua bidang dari hasil kami kecuali untuk namekolom (yang kami yakin ada, dari table1).

Meskipun ini mungkin bukan metode yang paling mungkin dilakukan dalam semua kasus, itu harus bekerja pada dasarnya setiap mesin basis data yang pernah mencoba untuk mengimplementasikan ANSI 92 SQL

Keris
sumber
16
@ z-boss: Ini juga yang paling sedikit performanya di SQL Server: jelasextended.com/2009/09/15/…
OMG Ponies
7
@ BunkerBoy: Gabung kiri memungkinkan baris di sebelah kanan tidak ada tanpa itu yang mempengaruhi masuknya baris di sebelah kiri. Gabungan dalam membutuhkan baris di sebelah kiri dan kanan untuk hadir. Apa yang saya lakukan di sini adalah menerapkan beberapa logika pada dasarnya untuk mendapatkan seleksi terbalik dari gabungan batin.
Kris
2
OMG ini membantu memvisualisasikan dengan sangat mudah, orang lain telah menempatkannya seperti 5 cara yang berbeda tetapi ini membantu. sederhana: pertama kamu gabung kiri, semua yang ada di A, dan semua yang ada di B yang cocok dengan A. Tapi seperti yang terjadi di gabung kiri yang tidak gabung sama saja nol. Lalu Anda katakan, ok saya hanya ingin itu nol. Dengan cara ini Anda sekarang memiliki semua baris dalam A yang tidak memiliki kecocokan Dalam B
Muhammad Umer
7
Perlu dicatat bahwa solusi ini (diterima dan dipilih) adalah satu-satunya, saya pikir, bisa diedit untuk skenario di mana lebih dari satu bidang ikut bermain. Khususnya, saya mengembalikan bidang, bidang 2, bidang 3 dari tabel satu di mana kombinasi bidang iklan bidang2 tidak ada di tabel kedua. Selain memodifikasi gabungan dalam jawaban ini, saya tidak melihat cara untuk melakukannya dengan beberapa "jawaban yang lebih efisien" yang diperdebatkan di bawah ini
TMWP
1
Pastikan Anda menggunakan "WHERE t2.name IS NULL" dan bukan "AND t2.name IS NULL" karena "dan" tidak akan memberikan hasil yang benar. Saya tidak benar-benar mengerti mengapa tetapi itu fakta, saya mengujinya.
user890332
236

Anda bisa melakukannya

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

atau

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

Lihat pertanyaan ini untuk 3 teknik untuk mencapai ini

froadie
sumber
38
Ini sangat lambat dengan sejumlah besar data.
Lightbulb1
Ya, memang sangat lambat
sirus
Bukankah seharusnya "dari table1" di subquery dari query tidak ada.
Hound
Sangat bingung bagaimana ini mendapat begitu banyak upvotes. Saya merasa sangat sulit untuk memikirkan alasan untuk menggunakan ini, ketika ada pendekatan untuk masalah ini yang sangat cepat dengan kira-kira jumlah penekanan tombol yang sama.
searchengine27
Yang ini bekerja untuk saya .. Terima kasih
Thameem
81

Saya tidak punya cukup poin rep untuk memilih jawaban ke-2. Tetapi saya harus tidak setuju dengan komentar di atas. Jawaban kedua:

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

Apakah JAUH lebih efisien dalam praktik. Saya tidak tahu mengapa, tapi saya menjalankannya melawan 800k + catatan dan perbedaannya luar biasa dengan keuntungan yang diberikan pada jawaban ke-2 yang diposting di atas. Hanya $ 0,02 saya

Tan Rezaei
sumber
30
Dalam permintaan NOT IN, subquery dilakukan hanya sekali, dalam permintaan EXISTS, subquery dilakukan untuk setiap baris
Carrick
1
Anda luar biasa :) dengan cara ini saya mengonversi kueri 25 detik menggunakan kiri bergabung menjadi hanya 0,1 detik
Bassem Shahin
3
jawaban tidak dalam urutan tertentu, jadi jawaban kedua tidak berarti apa yang Anda pikir artinya.
38

Ini adalah teori himpunan murni yang dapat Anda capai dengan minusoperasi.

select id, name from table1
minus
select id, name from table2
Musim dingin
sumber
Apakah Anda pikir ini jauh lebih efisien daripada gabung kiri?
Uh
Harus. Perintah minus dirancang untuk situasi yang tepat ini. Tentu saja satu-satunya cara untuk menilai set data tertentu adalah dengan mencoba keduanya dan melihat mana yang berjalan lebih cepat.
Musim dingin
9
Dalam T-SQL, operator yang ditetapkan adalah "kecuali". Ini sangat nyaman bagi saya dan tidak menyebabkan perlambatan.
2
Dalam SQLite, operator "minus" juga "kecuali".
Selamat bersenang
MySQL tidak mendukung operator MINUS.
Muhammad Azeem
16

Hati-hati terhadap jebakan. Jika bidang Namedi dalam Table1berisi Nulls Anda berada dalam kejutan. Lebih baik adalah:

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT ISNULL(name ,'')
     FROM table1)
pengguna4872693
sumber
1
COALESCE> ISNULL (ISNULL adalah tambahan T-SQL yang tidak berguna untuk bahasa yang tidak melakukan hal baru atau lebih baik daripada COALESCE)
Kris
14

Inilah yang paling cocok untuk saya.

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

Ini lebih dari dua kali lebih cepat daripada metode lain yang saya coba.

Bob
sumber
Terima kasih, Ini berfungsi baik dengan jumlah data yang besar juga! Tapi saya hanya ingin tahu tentang istilah 'Kecuali'.
PatsonLeaner
7

Itu berhasil bagi saya

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

Lihat kueri:

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

Secara konseptual akan menjadi: Mengambil catatan yang cocok di subquery dan kemudian di query utama mengambil catatan yang tidak ada di subquery.

jawahar
sumber
0

Saya akan memposting ulang (karena saya belum cukup keren untuk berkomentar) dalam jawaban yang benar .... kalau-kalau ada orang yang berpikir perlu menjelaskan lebih baik.

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

Dan saya telah melihat sintaks dalam FROM yang membutuhkan koma di antara nama tabel di mySQL tetapi dalam sqlLite sepertinya lebih menyukai spasi.

Intinya adalah ketika Anda menggunakan nama-nama variabel buruk itu meninggalkan pertanyaan. Variabel saya harus lebih masuk akal. Dan seseorang harus menjelaskan mengapa kita membutuhkan koma atau tidak koma.

Adrian Roth
sumber
0

Jika Anda ingin memilih pengguna tertentu

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

Ini tent_npkadalah kunci utama pengguna

Fragmantedbin
sumber