2010-01-16 14 views
129

Ich versuche, zwei Tabellen, SQL Server zu vergleichen, um einige Daten zu überprüfen. Ich möchte alle Zeilen von beiden Tabellen zurückgeben, in denen Daten entweder in der einen oder der anderen sind. Im Wesentlichen möchte ich alle Diskrepanzen zeigen. Ich muss dabei drei Daten prüfen, FirstName, LastName und Product.SQL Abfrage, um Unterschiede zwischen zwei Tabellen

Ich bin ziemlich neu in SQL und es scheint, als ob viele der Lösungen, die ich finde, über komplizierende Dinge sind. Ich muss mir keine Sorgen um NULL machen.

Ich begann so etwas wie dies versuchen:

SELECT DISTINCT [First Name], [Last Name], [Product Name] FROM [Temp Test Data] 
WHERE ([First Name] NOT IN (SELECT [First Name] 
FROM [Real Data])) 

Ich habe Probleme, obwohl diese weiter nehmen.

Danke!

EDIT:

Basierend auf der Antwort von @treaschf Ich habe eine Variation der folgenden Abfrage zu verwenden versucht:

SELECT td.[First Name], td.[Last Name], td.[Product Name] 
FROM [Temp Test Data] td FULL OUTER JOIN [Data] AS d 
ON td.[First Name] = d.[First Name] AND td.[Last Name] = d.[Last Name] 
WHERE (d.[First Name] = NULL) AND (d.[Last Name] = NULL) 

Aber ich erhalte immer 0 Ergebnisse zurück, wenn ich weiß, dass es ist mindestens 1 Zeile in TD, die nicht in d ist.

EDIT:

Ok, ich glaube, ich es herausgefunden. Zumindest in meinen wenigen Testminuten scheint es gut genug zu funktionieren.

SELECT [First Name], [Last Name] 
FROM [Temp Test Data] AS td 
WHERE (NOT EXISTS 
     (SELECT [First Name], [Last Name] 
     FROM [Data] AS d 
     WHERE ([First Name] = td.[First Name]) OR ([Last Name] = td.[Last Name]))) 

Das wird im Grunde genommen um mir zu sagen, was in meinen Testdaten, die nicht in meinen realen Daten sind. Was ist völlig in Ordnung für das, was ich tun muss.

+3

Das folgende EXCEPT-Beispiel ist etwa 100x schneller als dieses Beispiel. –

+0

kann jemand bestätigen, ob das funktioniert? funktioniert nicht an meinem Ende, sehe auch nicht den Punkt von "AS d", wenn "d" nirgendwo benutzt wird, könnte da irgendwo ein Fehler liegen? –

Antwort

139

Wenn Sie Tabellen A und B, beide mit colum C, hier sind die Aufzeichnungen, die A in der Tabelle vorhanden sind, aber nicht in B:

SELECT A.* 
FROM A 
    LEFT JOIN B ON (A.C = B.C) 
WHERE B.C IS NULL 

mit einer einzigen Abfrage alle Unterschiede zu erhalten,

SELECT A.*, B.* 
FROM A 
    FULL JOIN B ON (A.C = B.C) 
WHERE A.C IS NULL OR B.C IS NULL 

Was Sie in diesem Fall wissen müssen, ist, dass, wenn ein Datensatz in A gefunden werden, aber nicht in: ein voll anschließen müssen, das ist wie verwendet werden, dann sind die Spalten, die von B kommen, NULL, und ähnlich für diejenigen, die in B und nicht in A vorhanden sind, werden die Spalten von A null sein.

+0

Ich habe Probleme damit, das richtig zu machen, siehe meine letzte Bearbeitung oben. – Casey

+0

Das Problem könnte sein, dass Sie einen Wert nicht mit Null vergleichen können, indem Sie '=' verwenden. (Oder zumindest, wenn SET ANSI_NULLS auf ON gesetzt ist.) Sie müssen sagen: Wert IS NULL oder Wert IS NOT NULL. – treaschf

+0

Ich bezeichne dies als die Antwort, die ich verwendet habe, weil ich auf diese Weise einfach einige andere Dinge tun konnte, die ich später haben musste. – Casey

180
( SELECT * FROM table1 
    EXCEPT 
    SELECT * FROM table2) 
UNION ALL 
( SELECT * FROM table2 
    EXCEPT 
    SELECT * FROM table1) 
+0

+1: Dies ist der vernünftige Weg für SQL Server 2005+. – RedFilter

+0

* (Fehlende Aliase für Unterabfragen hinzugefügt.) * – RedFilter

+0

Ich erhalte Fehler bei der Verwendung. Ich ziehe die zwei Tabellen aus zwei verschiedenen Datenbanken –

2

Try this:

SELECT 
    [First Name], [Last Name] 
FROM 
    [Temp Test Data] AS td EXCEPTION JOIN [Data] AS d ON 
     (d.[First Name] = td.[First Name] OR d.[Last Name] = td.[Last Name]) 

Viel einfacher zu lesen.

34

Ich weiß, dass dies nicht eine beliebte Antwort sein kann, aber ich stimme @Randy Minder bei der Verwendung von Drittanbieter-Tool, wenn komplexere Vergleich benötigt wird.

Dieser spezielle Fall ist hier einfach und für diesen Fall werden solche Tools nicht benötigt, aber dies kann komplex werden, wenn Sie mehr Spalten, Datenbanken auf zwei Servern, komplexere Vergleichskriterien und solche einführen.

Es gibt viele dieser Tools wie ApexSQL Data Diff oder Quest Toad und Sie können sie immer im Testmodus verwenden, um die Arbeit zu erledigen.

+0

Ein Beispiel für eine FOSS-Datenbank-agnostische Lösung, die mit tabellarischen Datenquellen aus verschiedenen Datenbanken oder Dateisystemen funktioniert, ist [Diffkit] (http://www.diffkit.org/). – wwmbes

+0

Microsoft hat auch ein SQL Server 'tablediff' Befehlszeilenprogramm, auf das [hier] verwiesen wird (https://www.mssqltips.com/sqlservertip/1073/sql-server-tablediff-command-line-utility/). – wwmbes

4

Wenn Sie erhalten möchten, welche Spalte Werte unterschiedlich sind, könnten Sie Entity-Attribute-Value-Modell verwenden:

declare @Data1 xml, @Data2 xml 

select @Data1 = 
(
    select * 
    from (select * from Test1 except select * from Test2) as a 
    for xml raw('Data') 
) 

select @Data2 = 
(
    select * 
    from (select * from Test2 except select * from Test1) as a 
    for xml raw('Data') 
) 

;with CTE1 as (
    select 
     T.C.value('../@ID', 'bigint') as ID, 
     T.C.value('local-name(.)', 'nvarchar(128)') as Name, 
     T.C.value('.', 'nvarchar(max)') as Value 
    from @Data1.nodes('Data/@*') as T(C)  
), CTE2 as (
    select 
     T.C.value('../@ID', 'bigint') as ID, 
     T.C.value('local-name(.)', 'nvarchar(128)') as Name, 
     T.C.value('.', 'nvarchar(max)') as Value 
    from @Data2.nodes('Data/@*') as T(C)  
) 
select 
    isnull(C1.ID, C2.ID) as ID, isnull(C1.Name, C2.Name) as Name, C1.Value as Value1, C2.Value as Value2 
from CTE1 as C1 
    full outer join CTE2 as C2 on C2.ID = C1.ID and C2.Name = C1.Name 
where 
not 
(
    C1.Value is null and C2.Value is null or 
    C1.Value is not null and C2.Value is not null and C1.Value = C2.Value 
) 

SQL FIDDLE EXAMPLE

+0

Danke, ich habe diesen Code ein wenig dynamisch gemacht. Es erlaubt Ihnen jetzt, zwei Tabellen zu übergeben, die Sie vergleichen möchten ... http://thitos.blogspot.com/2014/03/compare-data-from-two-tables.html – Thato

+0

Arbeiten Sie wie ein Charme nur das diff Ich will. Vielen Dank – TypingPanda

1

Für einen einfachen Rauchtest, wo Sie Sie versuchen, um sicherzustellen, zwei Tabellen entsprechen etwa Spaltennamen sich Gedanken w/out:

--ensure tables have matching records 
Select count (*) from tbl_A 
Select count (*) from tbl_B 

--create temp table of all records in both tables 
Select * into #demo from tbl_A 
Union All 
Select * from tbl_B 

--Distinct #demo records = Total #demo records/2 = Total tbl_A records = total tbl_B records 
Select distinct * from #demo 

Sie können ganz einfach ein Geschäft Prozedur schreiben, einen Stapel von Tabellen zu vergleichen.

0

Es gibt ein Leistungsproblem im Zusammenhang mit dem linken Join sowie dem vollständigen Join mit großen Daten.

Meiner Meinung nach ist dies die beste Lösung:

select [First Name], count(1) e from (select * from [Temp Test Data] union all select * from [Temp Test Data 2]) a group by [First Name] having e = 1 
1

Dies wird den Trick tun, ähnlich wie mit Tiago ‚s Lösung, return‚Quelle‘Tabelle auch.

select [First name], [Last name], max(_tabloc) as _tabloc 
from (
    select [First Name], [Last name], 't1' as _tabloc from table1 
    union all 
    select [First name], [Last name], 't2' as _tabloc from table2 
) v 
group by [Fist Name], [Last name] 
having count(1)=1 

Ergebnis wird Unterschiede zwischen den Tabellen enthalten, in Spalte _tabloc haben Sie Tabellenreferenz.

4

Um alle Unterschiede zwischen zwei Tabellen zu erhalten, Sie wie ich diese SQL-Anfrage verwenden:

SELECT 'TABLE1-ONLY' AS SRC, T1.* 
FROM (
     SELECT * FROM Table1 
     EXCEPT 
     SELECT * FROM Table2 
    ) AS T1 
UNION ALL 
SELECT 'TABLE2-ONLY' AS SRC, T2.* 
FROM (
     SELECT * FROM Table2 
     EXCEPT 
     SELECT * FROM Table1 
    ) AS T2 
; 
1

Einfache Variante @erikkallen Antwort, die die Zeile vorhanden ist, in der Tabelle zeigt:

( SELECT 'table1' as source, * FROM table1 
    EXCEPT 
    SELECT * FROM table2) 
UNION ALL 
( SELECT 'table2' as source, * FROM table2 
    EXCEPT 
    SELECT * FROM table1) 
Verwandte Themen