2016-04-14 20 views
2

Verwenden von 2008 R2.Wie finden Sie ungepaarte Zeilen in TSQL?

Meine Tabelle sollte einige Zeilen enthalten, die gepaart sind - eine Cancel-Transaktion und eine Add-Transaktion, aber wir haben einige schlechte Daten, wo es nur eine Cancel gibt.

Ich versuche, diese zu identifizieren und sie zu beseitigen. Ich habe den folgenden Code ausprobiert, aber SQL hat den Fehler "Alle Abfragen, die mit einem UNION-, INTERSECT- oder EXCEPT-Operator kombiniert werden, muss eine gleiche Anzahl von Ausdrücken in ihren Ziellisten enthalten."

Wie kann ich diese nicht übereinstimmenden Zeilen identifizieren?

select * 
from dbo.mytable t 
where typename = 'Cancel' 
except 
Select * 
from dbo.mytable t1 
inner join dbo.mytable t2 
    on t1.id = t2.id 
where t1.typename = 'Cancel' 
and t2.typename = 'Add' 

Antwort

2

Sie haben die id Feld in der Auswahlliste angeben:

SELECT id 
FROM mytable 
WHERE typename = 'Cancel' 

EXCEPT 

SELECT id 
FROM mytable 
WHERE typename = 'Add' 

Die obige Abfrage die id Werte, für die wählt eine nicht angepaßte ‚Abbrechen‘ Datensatz vorhanden ist.

Alternativ können Sie verwenden eine LEFT JOIN:

SELECT t1.id 
FROM mytable t1 
LEFT JOIN mytable t2 ON t1.id = t2.id AND t2.typename = 'Add' 
WHERE t1.typename = 'Cancel' AND t2.id IS NULL 
+0

Danke - sie beide arbeiteten (jetzt, warum habe ich nicht daran gedacht?). Die erste Abfrage, die Sie vorgeschlagen haben, gab 3 eindeutige Zeilen zurück, während die zweite 10 Zeilen zurückgab, die Duplikate enthielten (für diese ID). – DeveloperM

1

Try this:

select id 
from dbo.mytable t 
where typename = 'Cancel' 
except 
Select id 
from dbo.mytable t1 
inner join dbo.mytable t2 
    on t1.id = t2.id 
where t1.typename = 'Cancel' 
and t2.typename = 'Add' 
+0

Vielen Dank für Ihre Antwort. Diese Abfrage dauerte viel länger als die von @Giorgos Betsos vorgeschlagenen und ergab 32 Zeilen in 50 Sekunden (einschließlich einiger Duplikate für diese ID), obwohl sie viel schneller lief, als ich die Ausführung wiederholte. Ich denke, ich werde mit seinem Vorschlag gehen. – DeveloperM

0
SELECT * 
FROM (
     SELECT *, 
       SUM(CASE typename WHEN 'add' THEN 1 END) OVER (PARTITION BY id) addcnt, 
       SUM(CASE typename WHEN 'cancel' THEN 1 END) OVER (PARTITION BY id) cancelcnt 
     FROM mytable 
     ) q 
WHERE addcnt IS NULL 
     AND cancelcnt > 0 

Dadurch wird alle Transaktionen auszuwählen, die eine in ihnen aufheben, aber keinen Zusatz, einschließlich anderen möglichen Typen .