Laden...

[gelöst] SQL Query - aktuellster Datensatz

Erstellt von Lion1984 vor 15 Jahren Letzter Beitrag vor 15 Jahren 3.589 Views
L
Lion1984 Themenstarter:in
770 Beiträge seit 2006
vor 15 Jahren
[gelöst] SQL Query - aktuellster Datensatz

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

Gelöschter Account
vor 15 Jahren

kannst du an der datenbankstruktur was drehen? das da ist ein eher suboptimales versionierungssystem.

L
Lion1984 Themenstarter:in
770 Beiträge seit 2006
vor 15 Jahren

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

Gelöschter Account
vor 15 Jahren

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:

  1. hans | jürgen | 10.10.2000 | inserted | 01.01.2008
  2. hans | jürgen | 11.10.1918 | inserted | 01.01.2008
  3. hans | jürgenn | 10.10.2008 | changed | 02.01.2008

nie wissen kannst, welcher der beiden datensätze der alte ist.

edit (copy&paste fehler...)

1.378 Beiträge seit 2006
vor 15 Jahren

SELECT *
FROM
(
	SELECT *, ROW_NUMBER(PARTITION BY Name, Email[,.. weitere Gruppierungsfelder] ORDER BY Id DESC) RowNumber
	FROM Tabelle
)tmp
WHERE RowNumber=1

Lg XXX

Gelöschter Account
vor 15 Jahren

@xxxprod
da hast du immernoch das problem, das du auch einträge bekommst, die dort nicht hereingehören. sprich überschreibene einträge.

5.742 Beiträge seit 2007
vor 15 Jahren

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.

1.696 Beiträge seit 2006
vor 15 Jahren

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

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

1.378 Beiträge seit 2006
vor 15 Jahren

@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

Gelöschter Account
vor 15 Jahren

@vbprogger

auch dein select scheitert an:

das problem ist, das du in dieser art der versionierung im hypothetischem fall von:

  1. hans | jürgen | 10.10.2000 | inserted | 01.01.2008
  2. hans | jürgen | 11.10.1918 | inserted | 01.01.2008
  3. 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.

1.696 Beiträge seit 2006
vor 15 Jahren

Ich gehe davon aus, dass man vernünftigerweise DateTime hat und nicht nur Date 😁 😁

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

Gelöschter Account
vor 15 Jahren

@vbprogger

das macht in diesem fall kein unterschied.

L
Lion1984 Themenstarter:in
770 Beiträge seit 2006
vor 15 Jahren

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

Gelöschter Account
vor 15 Jahren

also gut ich gebs auf hier auf einen offensichtlichen fehler hinzuweisen. wenn du der meinung bist, das es funktioniert. bitte sehr.

edit: vorweg: das ist nciht böse gemeint.

L
Lion1984 Themenstarter:in
770 Beiträge seit 2006
vor 15 Jahren

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:

  1. hans | jürgen | 10.10.2000 | inserted | 01.01.2008
  2. hans | jürgen | 11.10.1918 | inserted | 01.01.2008
  3. hanss | jürgenn | 10.10.2008 | changed | 02.01.2008

würde zu folgendem werden:

  1. hans | jürgen | 10.10.2000 | inserted | 01.01.2008 | ItemA
  2. hans | jürgen | 11.10.1918 | inserted | 01.01.2008 |ItemB
  3. hanss | jürgenn | 10.10.2008 | changed | 02.01.2008 |ItemA

Von daher weiß ich, welcher Datensatz der gleiche ist und würde im join doch beinhalten, oder nicht? (ON ItemA = ItemA).

Lion

lg Lion

1.696 Beiträge seit 2006
vor 15 Jahren

@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 🙂

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

Gelöschter Account
vor 15 Jahren

@Lion1984

das ist eine wichtige info....

somit lösen sich auch die probleme in luft auf.

L
Lion1984 Themenstarter:in
770 Beiträge seit 2006
vor 15 Jahren

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

1.378 Beiträge seit 2006
vor 15 Jahren

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