Duplikate einer spalte nach kriterium entfernen

Hallo SQL-Experten,
danke nochmal für die Hilfe das letzte Mal.

Noch eine Frage bzgl. der Umformulierung meiner Befehle (Access -> SQL Server).
Es geht um eine Anfügeabfrage einer Tabelle, die mir Duplikate einer Spalte entfernen soll. Das Ergebnis sollen die Datensätze sein, welche das früheste Datum einer anderen Spalte besitzen. Jede KKS darf nur einmal vorkommen in der Zieltabelle.

Bsp.:
KKS System Datum
1 A 02.01.2011
1 B 01.01.2011
2 A 03.01.2011

Ergebnis:
KKS System Datum
1 B 01.01.2011
2 A 03.01.2011

In Access hab ich einfach sortiert und alles in eine neue Tabelle angefügt. Die Duplikate, also wenn die KKS schon vorhanden war, wurden einfach nicht übernommen (mit Warnmeldung, aber das war mir egal). Auf dem SQL Server kann ich aber die Anfügeabfrage/Prozedur nicht machen, da der Vorgang abgebrochen wird (KKS ist Primärschlüssel). Folgende Fehlermeldung erscheint:

Violation of PRIMARY KEY constraint ‚PK_Zieltabelle‘. Cannot insert duplicate key in object ‚dbo.Zieltabelle‘.
The statement has been terminated.

Ich muss also irgendwie schon vorher sortieren und die Duplikate rauswerfen und dann an meine Zieltabelle anfügen. Könnt ihr mir helfen? Ich schreib meine Masterarbeit über das System und komm einfach nicht weiter. Wie viele Zwischentabellen, Unterabfragen brauche ich?
Am besten wäre es, wenn mir jemand direkt die Befehle aufschreiben kann.

Vielen Dank schon mal im Voraus

Gruß

Armin

Hallo Armin,

ich fasse mal zusammen: Es ist der älteste Eintrag (bzgl. Datum) je KKS gesucht. Hab ich das richtig verstanden?

Mal ein Schnellschuss:

SELECT KKS, System, Datum
FROM tabelle t1 JOIN (SELECT KKS, min(Datum) as Datum
 FROM tabelle
 GROUP BY KKS) t2 
 ON (t1.KKS = t2.KKS AND t1.Datum = t2.Datum)

Die innere Abfrage ermittelt das älteste Datum je KKS. Der Join ist nötig, um die Spalte System zu holen. Man könnte es auch als korrelierte Unterabfrage formulieren. Aber das Ergebnis ist das Gleiche.

Ob ein Einfügen in eine andere Tabelle nötig ist, kann ich nicht beurteilen. Aber eine View könnte auch helfen:

CREATE VIEW ziel AS
SELECT KKS, System, Datum
FROM tabelle t1 JOIN (SELECT KKS, min(Datum) as Datum
 FROM tabelle
 GROUP BY KKS) t2 
 ON (t1.KKS = t2.KKS AND t1.Datum = t2.Datum)

Peter

Hallo Peter,

funktioniert, super.
Wenn ich das richtig verstanden habe, nutzte ich die zweite Tabelle (welche in der inneren Abfrage erst beschrieben wird) nur, um mit der INNER JOIN zu vergleichen. Sie bleibt nach der Abfrage leer, aber das ist okay, da ich ja mit der Sicht weiterarbeiten kann.

Danke für die Hilfe, ich hab echt lang gesucht in diesem und anderen Foren und bin auf nichts passendes gestoßen. Klasse hier:smile:

Armin

Hallo Armin,

was ist mit

Sie bleibt nach der Abfrage leer, …

gemeint? Die innere Abfrage liefert die benötigten Werte für die Spalten KKS und Datum.

Peter

Hallo Peter,

naja, ich habe eine zweite Tabelle mit den gleichen Spalten, nur ohne Inhalt, erstellt. Dann läuft deine Abfrage drüber und die Tabelle wird nicht beschrieben (was ich eigentlich zuerst wollte). Jetzt ist mir aber klar, dass ich ja mit der Sicht weiterarbeiten kann. Ist sogar besser so, da ich mir glaub später noch ein paar Tabellen sparen kann… mal sehen.
Danke nochmals für deine klasse Lösung!

Gruß, Armin,
der vllt noch einmal auf dich zurückkommen wird^^

Hallo Peter und Mitleser,

ein Problem bzgl. deiner Abfrage hab ich noch.
In der Abfrage sind noch KKSn doppelt vorhanden. Es handelt sich um die KKS, bei denen das Datum gleich, aber das System verschieden ist. Als Beispiel die erweiterte Tabelle

KKS System Datum
1 A 02.01.2011
1 B 01.01.2011
2 A 03.01.2011
2 B 03.01.2011

Derzeit habe ich die beiden letzten Zeilen im Ergebnis stehen. Ziel soll aber nur noch eine der Zeilen (KKS=2) sein, welche ist egal.
Hast du eine Idee? Wollte eben doppelt gruppieren, kam aber auf keine Lösung…

Danke,

Gruß, Armin

Hallo Armin,

wenn Du sagst:

Ziel soll aber nur noch eine der Zeilen (KKS=2) sein, welche
ist egal.

lautet die Aufgabenstellung eigtl. so:
Gesucht ist eine beliebige Zeile mit dem ältesten Datum je KKS.

Die „unerwünschte“ Zeile ergibt sich erst durch den Join. Daher muss darauf noch eine weitere Abfrage angewendet werden.
Die Abfrage könnte dann wie folgt aussehen:

WITH t3 as (
 SELECT t1.KKS, t1.System, t1.Datum
 FROM tabelle t1 
 JOIN (SELECT KKS, min(Datum) as Datum
 FROM tabelle
 GROUP BY KKS) t2 ON (t1.KKS = t2.KKS AND t1.Datum = t2.Datum)
)
SELECT t3.KKS, t3.System, t3.Datum
FROM t3 
 JOIN (SELECT KKS, min(System) as System
 FROM t3
 GROUP BY KKS) t4 ON (t3.KKS = t4.KKS and t3.System = t4.System)
;

Mittels WITH wird eine Common Table Expression formuliert. Das erspart das wiederholte Notieren der Abfrage überall dort, wo t3 steht. Man kann t3 aber auch mittels View oder temporärer Tabelle formulieren, je nach Anwendungsfall.
Die Abfrage, die zu t4 führt, liefert das kleinste System (bzgl. alphabetischer Sortierung) je KKS. Es wäre auch max(System) denkbar. Da eine beliebige Zeile gewählt werden soll, ist es gleich.

HTH
Peter

Peter, unglaublich, du bist ein Fuchs.
Neben der Richtigstellung meiner Frage konnte ich eben auch deinen Befehl verwenden und es sieht verdammt gut aus:smile:
Das hat wirklich geholfen. Gruß, Armin