ÇÖZÜMLER HAKKINDA UYARI:
BİRKAÇ MEVCUT ÇÖZÜM, SIRA BENZERSİZ DEĞİLSE YANLIŞ ÇIKTI VERECEK
Tablo oluşturan tek kişi sizseniz, bu uygun olmayabilir, ancak birkaç çözüm, tablolardan biri benzersiz satırlar içermeyebileceği zaman, söz konusu koddan farklı sayıda çıktı satırı verecektir.
SORUN BİLDİRİMİ HAKKINDA UYARI:
BİRDEN FAZLA KOLON VARSA, İSTEDİĞİNİZİ DİKKATLİCE DÜŞÜNÜN
İki sütunlu bir giriş gördüğümde, bunun iki anlama geldiğini hayal edebilirim:
- A sütununun ve b sütununun değeri diğer tabloda bağımsız olarak görünür
- A sütununun ve b sütununun değerleri diğer tabloda aynı satırda birlikte görünür
Senaryo 1 oldukça önemsizdir, sadece iki IN ifadesi kullanın.
Mevcut cevapların çoğuna uygun olarak, Senaryo 2 (ve kısa bir karar) için bahsedilen ve ek yaklaşımlara genel bir bakış sunuyorum:
EXISTS (Güvenli, SQL Server için önerilir)
@Mrdenny tarafından sağlanan EXISTS, tam olarak aradığınız gibi geliyor, işte onun örneği:
SELECT * FROM T1
WHERE EXISTS
(SELECT * FROM T2
WHERE T1.a=T2.a and T1.b=T2.b)
SOL SEMI JOIN (Güvenli, onu destekleyen lehçeler için önerilir)
Bu katılmak için çok kısa bir yol, ama ne yazık ki SQL sunucusu da dahil olmak üzere çoğu SQL lehçeleri şu anda desteklemiyor.
SELECT * FROM T1
LEFT SEMI JOIN T2 ON T1.a=T2.a and T1.b=T2.b
Çoklu IN ifadeleri (Güvenli, ancak kod çoğaltmasına dikkat edin)
@Cataclysm tarafından iki IN ifadesi kullanılarak belirtildiği gibi, hile yapabilir, belki de diğer çözümlerden daha iyi performans gösterebilir. Ancak, çok dikkatli olmanız gereken kod çoğaltmasıdır. Farklı bir tablodan seçim yapmak veya where deyimini değiştirmek isterseniz, mantığınızda tutarsızlıklar yaratma riskiniz artar.
Temel çözüm
SELECT * from T1
WHERE a IN (SELECT a FROM T2 WHERE something)
AND b IN (SELECT b FROM T2 WHERE something)
Kod çoğaltma olmadan çözüm (Bu normal SQL Server sorgularında çalışmaz inanıyorum)
WITH mytmp AS (SELECT a, b FROM T2 WHERE something);
SELECT * from T1
WHERE a IN (SELECT a FROM mytmp)
AND b IN (SELECT b FROM mytmp)
INNER JOIN (teknik olarak güvenli hale getirilebilir, ancak genellikle bu yapılmaz)
Bir iç birleşimi filtre olarak kullanmanızı önermememin nedeni, pratikte insanlar genellikle sağ tablodaki kopyaların sol tablodaki kopyalara neden olmasına neden olur. Ve daha sonra, konuları daha da kötüleştirmek için, bazen nihai sonucu farklı kılarlar, ancak sol tablonun aslında benzersiz olması (veya seçtiğiniz sütunlarda benzersiz olmaması) gerekmeyebilir. Dahası, sol tabloda bulunmayan bir sütunu gerçekten seçme şansı verir.
SELECT T1.* FROM T1
INNER JOIN
(SELECT DISTINCT a, b FROM T2) AS T2sub
ON T1.a=T2sub.a AND T1.b=T2sub.b
En yaygın hatalar:
- Güvenli bir alt sorgu olmadan doğrudan T2'ye katılmak. Tekrarlama riskiyle sonuçlanan)
- SELECT * (T2'den sütun alma garantisi)
- SELECT c (Sütununun geldiğini ve her zaman T1'den geleceğini garanti etmez)
- Yanlış yerde DISTINCT veya DISTINCT yok
KOLONLARIN SEPARATÖR İLE KONTROL EDİLMESİ (Çok güvenli değil, korkunç performans)
İşlevsel sorun, bir sütunda meydana gelebilecek bir ayırıcı kullanırsanız, sonucun% 100 doğru olmasını sağlamak zorlaşır. Teknik sorun, bu yöntemin genellikle tür dönüşümleri gerçekleştirmesi ve dizinleri tamamen göz ardı etmesi ve muhtemelen korkunç bir performansla sonuçlanmasıdır. Bu sorunlara rağmen, itiraf etmeliyim ki bazen hala küçük veri kümelerindeki geçici sorgular için kullanıyorum.
SELECT * FROM T1
WHERE CONCAT(a,"_",b) IN
(SELECT CONCAT(a,"_",b) FROM T2)
Sütunlarınız sayısalsa, bazı SQL lehçelerinin önce bunları dizelere yayınlamanızı gerektireceğini unutmayın. SQL sunucusunun bunu otomatik olarak yapacağına inanıyorum.
Bir şeyleri toparlamak için: Her zamanki gibi bunu SQL'de yapmanın birçok yolu vardır, güvenli seçimler kullanmak sürprizlerden kaçınır ve uzun vadede size zaman ve baş ağrısı kazandırır.