2016-04-13 17 views
0

İki alanda (ContractState, TransID) temel alan eşleşen bir kayıt bulunmayan bir tabloda veri bulmak istiyorum. ÖrneğinSadece eşleşen kayıtları olmayan bir tablodaki verileri bulmak için SQL

, bu veri kümesi varsayalım (gerçekte, tüm veri setleri sadece birkaç dahil ediyorum, kayıtların yüzlerce içerir):

AccountNbr ContractState TransID  Product 
3335477  AL    80079  DPPO, DHMO 
3335477  AL    80080  PPO 
3335477  AR    80079  DPPO, DHMO 
3335477  AR    80080  PPO 

Bu 0 kayıtları dönmelidir, 2 kayıt oluşturduğu için AL için (her TransID için bir tane) ve AR için 2 kayıt. her bir durum için, sadece 1 TransID çünkü

AccountNbr ContractState TransID  Product 
3335477  DE    80079  DHMO 
3335477  WA    80080  DHMO 

:

AccountNbr ContractState TransID  Product 
3335477  AL    80079  DPPO, DHMO 
3335477  AL    80080  PPO 
3335477  DE    80079  DHMO 
3335477  WA    80080  DHMO 

sadece aşağıdaki veri kümesi geri istiyoruz:

Bununla birlikte, aşağıdaki veri seti verilmiştir.

Bu kodu vardır, ama aynı zamanda eşleşen verileri ile kayıtları içerir:

SELECT 
    'tblSQLContractState' as TableName, 
    TransID, 
    ContractState, 
    Product, 
    COUNT(*) AS [NumOfMessage] 
FROM tblSQLContractState 
WHERE TransID IN (80079, 80080) 
GROUP BY 
    TransID, 
    ContractState, 
    Product 
HAVING COUNT(*) = 1 
+0

Tüm 3 cevap güzeldi ve işe yaradı, ama ben Gordon'la gittim çünkü daha kolay düzenlenecek gibi görünüyordu ve 20 farklı tablo için benzer bir sorgu yapıyorum. Giriş için teşekkürler, hepiniz! –

+0

O halde kabul et :) –

cevap

1

kullanın pencere fonksiyonları. Sağladığınız veriler için bu çalışması gerekir: Bu ContractState orada bu TransId başka kaydıdır ancak nerede

select cs.* 
from (select cs.*, 
      count(*) over (partition by AccountNbr, ContractState) as cnt 
     from tblSQLContractState cs 
     where TransID IN (80079, 80080) 
    ) cs 
where cnt = 1; 
1

Sen kayıtları seçmek için bir NOT EXISTS kullanabilirsiniz:

SELECT 
    'tblSQLContractState' as TableName, 
    cs.AccountNbr, cs.ContractState, cs.TransID, cs.Product 
FROM tblSQLContractState cs 
WHERE cs.TransID IN (80079, 80080) 
AND NOT EXISTS         -- no other record 
(
    SELECT 1 FROM tblSQLContractState cs2 
    WHERE cs2.TransID <> cs.TransID    -- with other TransId 
     AND cs2.ContractState = cs.ContractState -- and this ContractState 
) 

NOT EXISTS oldukça verimlidir SQL Server'da ve kolayca değiştirilebilir/genişletilebilir. Diğer bir avantaj ise, GROUP BY'un aksine tüm sütunları seçebilmenizdir.

1

Sorunuz yakın. Ancak, ContractState için bir sonuç satırı istersiniz - ve aynı zamanda kayıtların sayısını (aggreate COUNT(*)) bilmek istediğiniz bu özelliktir. Yani Product ve TransID'u GROUP BY maddesinden kaldırın.

Yalnızca göstermek istediğiniz sıra sayısı 1 olan kombinasyonlar olduğu için, söz konusu ürünü almak için MIN(Product) veya MAX(Product) kullanabilirsiniz. TransID için de geçerlidir.

SELECT 
    'tblSQLContractState' as TableName, 
    MAX(TransID) AS TransID, 
    ContractState, 
    MAX(Product) AS Product, 
    COUNT(*) AS [NumOfMessage] 
FROM tblSQLContractState 
WHERE TransID IN (80079, 80080) 
GROUP BY ContractState 
HAVING COUNT(*) = 1; 

Gordon'un cevabı daha düz ve daha genel kullanım içindir. Bunu çözmek için sadece doğal yolu bence. Sadece sorgunuzun çok yakın olduğunu göstermek istedim :-)

GÜNCELLEME: Tim'in cevabı da çok iyi. (Benim yazdığımda orada değildi.) O haklı; Tüm bilmek istediğiniz, ContractState için başka bir kayıt olup olmadığıdır, dolayısıyla varolan bir madde uygundur.

İlgili konular