2016-08-15 3 views
0

Ich habe eine lokale Benutzertabelle, die Daten von unserem Client erhält. Einmal pro Woche liefern sie uns eine aktualisierte Version ihrer Benutzerdaten. Wir müssen dann neue Benutzer in unsere Benutzertabelle eintragen (das ist einfach), und alle bestehenden Benutzer mit neuen Daten aktualisieren (hier stehe ich fest).SQL-Abfrage, um falsch passende Daten zu finden

Nehmen wir an, unsere lokale Tabelle heißt UserLocal, und dann haben wir eine Tabelle, die einmal pro Woche mit den neuen Daten vom Client namens UserNew gelöscht und neu geschrieben wird. Die Säulen, mit einer Probe von einem Nutzer, der wie folgt aussieht:

UserLocal 

UserId UserCode FirstName LastName 
12345  ABC   John   Doe 

Aber die neue Datenfeed von dem Client wie folgt aussieht:

UserNew 

UserId UserCode FirstName LastName 
12345  XYZ   John   Doe 

So hat sich die Usercode für John geändert. Was ich versuche, ist eine Abfrage zu schreiben, die alle Zeilen in UserNew findet, wo die UserId mit einer Zeile in UserLocal übereinstimmt, aber der UserCode nicht übereinstimmt.

Ich habe eine harte Zeit mit dieser Syntax.

+0

Ist 'UserId' Primärschlüssel in beiden Tabellen? Zeig DDL bitte. – Serg

+0

Es ist nicht als Primärschlüssel festgelegt, aber der Wert ist eindeutig –

+0

Sie haben sn.Student_ID_Number = sn.Student_ID_Number in Ihrer Abfrage oben - daher die mehreren Zeilen :-) Sollte es sn.Student_ID_Number = s.Student_ID_Number sein? – bhs

Antwort

2

würde Die Grundidee sein:

SELECT * 
FROM UserNew n 
    JOIN UserLocal l 
     ON l.UserId = n.UserId 
     AND l.UserCode != n.UserCode 
+0

Ja, das war das erste, was ich ausprobiert habe. Es wird die Arbeit nicht erledigt. Es läuft für 30+ Sekunden und gibt Tausende von doppelten Zeilen zurück. Scheint logisch, funktioniert aber nicht –

+0

Sind Sie sicher, dass Sie nur einen Datensatz für jeden Benutzer in jeder Tabelle haben? –

+0

Ich habe gerade überprüft. Ja. Eindeutige Zeilen pro Benutzer in beiden Tabellen. –

1

Sie müssen den MERGE Befehl verwenden. Es wird zum Aktualisieren oder Einfügen von Datensätzen in eine Tabelle verwendet, genau wie Sie es benötigen.

Es gibt viele Beispiele im Internet und Details des Befehls kann here

+0

Ok danke BHS. Ich werde irgendwann zu dem Punkt kommen, an dem ich die Daten zusammenführe. Im Moment muss ich nur sehen können, wie viele Zeilen zusammengeführt werden und welche Zeilen sie sind. –

+0

Die Zusammenführung ist einfach zu schreiben - die OUTPUT-Klausel kann Ihnen auch die Details von Einfügungen und Updates geben – bhs

+0

ok, ich werde dies betrachten. Danke –

0

Sie merge oder drei DML-Anweisungen verwenden können ..

Insert into localtable 
     select * from clienttable ct 
     where not exists(select 1 from localtable t where t.userid=ct.userid) 

--delete..not exists also can be used 

delete lc 
from 
localtable lc 
join 
clinettable ct 
on ct.userid<>lc.userid 


---update 

;With cte 
as 
(
select * from clienttable 
except 
select * from localtbale 
) 
update lc 
set lc.usercode=c.usercode 
--do for all columns 
set 
from 
localtable lc 
join cte c 
on c.userid=lc.userid 
1

gefunden werden Wenn Sie sehen möchten, und/oder Nachverfolgen von Änderungen vor der MERGE

Declare @UserLocal table (UserId int,UserCode varchar(50),FirstName varchar(50),LastName varchar(50)) 
Insert Into @UserLocal values (12345,'ABC','John','Doe') 

Declare @UserNew table (UserId int,UserCode varchar(50),FirstName varchar(50),LastName varchar(50)) 
Insert Into @UserNew values (12345,'XYZ','Johnnny','Doe') 

Declare @XML xml 
Set @XML = (Select * From (Select Ver=0,* from @UserLocal Union All Select Ver=1,* from @UserNew) A for XML RAW) 
;with cteBase as (
    Select UserId  = r.value('@UserId','int') 
      ,Ver   = r.value('@Ver','int') 
      ,Item   = Attr.value('local-name(.)','varchar(max)') 
      ,Value  = Attr.value('.','varchar(max)') 
    From @XML.nodes('/row') AS A(r) 
    Cross Apply A.r.nodes('./@*[local-name(.)!="Ver"]') AS B(Attr) 
) 
,cteExt as (Select *,LastValue =Lag(Value) over (Partition By UserID,Item Order by Ver) From cteBase) 
Select UserID 
     ,Item 
     ,Before=LastValue 
     ,After =Value 
From cteExt 
Where Value<>LastValue and LastValue is not null 
Order By UserID,Item 

Returns

UserID Item  Before After 
12345 FirstName John Johnnny 
12345 UserCode ABC  XYZ 
Verwandte Themen