verwendetes Datenbanksystem: MS SQL 2005
Hallo Forum,
Ich habe eine Tabelle, die bestimmte Informationen enthält (Beispiel: Name, email, Alter, typ, changed).
Nun erhalte ich über eine Replication (welche nicht von lokalen Mitarbeitern eignerichtet wurde) Informationen über den Datenbestand einer fremden Anwendung. Dies sieht so aus, dass es für jede Änderung eine eigene Reihe gibt, nur der typ und changed unterschiedlich sind.
ich versuche mal das darzustellen wie ich das erhalten würde
1 Name1 email1 Alter1 Inserted 01.01.2008
2 Name2 email2 Alter2 Inserted 05.01.2008
3 Name1 email1 neuesAlter Changed 10.11.2008
Also ich erhalte immer einen kompletten Datensatz, so wie er gültig ist. D.h. gibt es nun einen neuen Eintrag und 4 Änderungen, habe insgesamt 5 Datensätze und der letzte ist gültig.
Nun kann ich leider die anderen nicht löschen, aber für eine Abfrage bräuchte ich eben jeweils nur die gültigen Daten aller Reihen. z.B. anhand der oben erhaltenen Einträge würde ich folgenendes Resultat benötigen:
2 Name2 email2 Alter2 Inserted 05.01.2008
3 Name1 email1 neuesAlter Changed 10.11.2008
Gibt es hierfür einen "einfachen" SQL Befehl? Bzw. wie löse ich so eine Abfrage?
Lion
lg Lion
nein, wir hier in der IT sind auch damit ganz und gar nicht glücklich.
also, ich korrigiere..
ich habe 2 schemas, das eine wird vom "Lieferanten" verwaltet, das andere von uns, das nennt sich History. Ist genau das gleiche nur beinhaltet es sämlichte Daten, die bislang geliefert wurden, da derren Tabellen regelmäßig gelöscht werden.
Ich hatte mir schon überlegt, in diesen Kopierprocess, der die Daten von SchemaA nach SchemaB schaufelt (ich schreib absichtlich SchemaA/B, da wie erwähnt, der Inhalt beider Schema's gleich ist).
Nur dann würden sich da die selben Daten ansammeln und eigentlich eine unnötige doppelte Aufbewahrung, daher kam ich auf die Idee bzw. versuchte ich, dass über die oben genannte / gewünschte SQL Query zu lösen.
Es ist eigentlich kein versionierungssystem.. es ist eine Lieferung spezieller Daten, die ich z.B. in Firmen interne Anwendungen inkludieren kann.
Lion
lg Lion
Es ist eigentlich kein versionierungssystem.. es ist eine Lieferung spezieller Daten, die ich z.B. in Firmen interne Anwendungen inkludieren kann.
versionierung bedeutet ja, das man weiß was sich wann und vor allem wie geändert hat. das machst du hier auch nur ist es unglücklicherweise in einem unvorteilhaften format/schema beigelegt.
das problem ist, das du in dieser art der versionierung im hypothetischem fall von:
nie wissen kannst, welcher der beiden datensätze der alte ist.
edit (copy&paste fehler...)
SELECT *
FROM
(
SELECT *, ROW_NUMBER(PARTITION BY Name, Email[,.. weitere Gruppierungsfelder] ORDER BY Id DESC) RowNumber
FROM Tabelle
)tmp
WHERE RowNumber=1
Lg XXX
Wenn ich mich nicht irre, kann man das ohne die innere Abfrage realisieren, indem man TOP 1
verwendet.
ORDER BY
wird nämlich IMHO vorher abgearbeitet; man erhält also die erste Zeile des sortierten Ergebnis und nicht die erste Zeile, die dann sortiert wird.
Hallo Lion1984,
du möchtest also jeweils den neuesten Datensatz? Wenn ja, probiere mal mit dem selfjoin wie folgt:
select a.*
from Tabelle a left join Tabelle b
on a.[Name]=b.[Name] and a.changed<b.changed
where b.changed is null
**:::
@xxxprod
da hast du immernoch das problem, das du auch einträge bekommst, die dort nicht hereingehören. sprich überschreibene einträge.
Sehe ich jetzt nicht so... wenn die Gruppierungsfelder richtig gewählt sind sollte die Abfrage funktionieren. Sofern die erste Spalte eine Autoinkrementelle id-spalte ist(was ich annehme).
Vielleicht kannst du ein Beispiel posten, wie du dir vorstellst das die Abfrage scheitern könnte?
Lg XXX
@vbprogger
auch dein select scheitert an:
das problem ist, das du in dieser art der versionierung im hypothetischem fall von:
- hans | jürgen | 10.10.2000 | inserted | 01.01.2008
- hans | jürgen | 11.10.1918 | inserted | 01.01.2008
- hanss | jürgenn | 10.10.2008 | changed | 02.01.2008
nie wissen kannst, welcher der beiden datensätze der alte ist.
@xxxprod:
siehe obiges beispiel.
Ich gehe davon aus, dass man vernünftigerweise DateTime hat und nicht nur Date 😁 😁
**:::
Hallo @all,
also mal vorweg, ja ich habe natürlich ein DateTime (oben war nur ein Beispiel) und ich habe auch eine Spalte, mit der ich den Datensatz eindeutig und 100% zuordnen kann. Mir ging es nur darum, jeweils den aktuellsten Satz zu holen, sorry wenn ich mich unverständlich ausgedrückt habe.
@xxxprod
Deinen Code habe ich leider nicht zum laufen bekommen, versuche das aber auch hinzukriegen.
@vbprogger, JAck30lena
Der Ansatz scheint zu funktionieren, ich mach nurmehr stichproben ob es auch stimmt..
Das Feld, auf das ich vergleiche nennt sich "TimeStamp", beinhaltet einen Timestamp, ist aber ein varchar(26), ich erwähne wieder, Lieferanten ..
Daher müßte doch der Vergleich funktionieren, oder nicht?
Danke vorerst, an allen Helfern!
Lion
€dit:
Die Tabellen beinhalten eine AutiID Spalte, aber die beziehe ich nicht ein.
lg Lion
Bitte gebe nicht auf mir den Fehler klar zu machen.
Ich habe eben geschrieben, ich habe ein Feld welches die Zeile genau zuweißt, also in deinem Beispiel:
würde zu folgendem werden:
Von daher weiß ich, welcher Datensatz der gleiche ist und würde im join doch beinhalten, oder nicht? (ON ItemA = ItemA).
Lion
lg Lion
@vbprogger
das macht in diesem fall kein unterschied.
Ein DateTime beinhaltet normalerweise auch Milisekundenwerte. IMHO gibt es äußerst selten der Fall, dass 2 Datensätze den absolut gleichen Wert haben.
Aber recht hast du 🙂
**:::
wie erwähnt, ich habe mich entschuldigt es im ersten Post nicht geschrieben zuhaben. Ich dachte es sei klar, dass ich die Infos eindeutig zuweißen kann. Aus Fehlern lernt man, und sei es nur bei der Fragestellung 😉
Daher auch mein Post, es siehe gut aus. Ohne der Spalte verstehe ich natürlich von dir angesprochene Problem.
Lion
lg Lion
Hab die Abfrage leicht angepasst und einen Fehler ausgebessert(AS für den Aliasnamen vergessen). So sollte es dann funktionieren:
SELECT *
FROM
(
SELECT *, ROW_NUMBER(PARTITIONBY <IdentifizierendesFeld> ORDER BY <AutoIncrementellemFeld> DESC) AS RowNumber
FROM Tabelle
)tmp
WHERE RowNumber=1
Lg XXX