2009-08-24 7 views
2

Wie schreibt man eine Anweisung, um die folgenden zu erreichen?löschen alle bis auf minimale Werte, basierend auf zwei Spalten in SQL Server-Tabelle

sagen lässt eine Tabelle 2 Spalten (beide sind nvarchar) mit folgenden Daten

col1 10000_10000_10001_10002_10002_10002 
col2 10____20____10____30____40_____50 

Ich möchte nur folgende Daten halten:

col1 10000_10001_10002 
col2 10____10____30 

somit die Duplikate zu entfernen Basis in den Werten der zweiten Spalte (keine der Spalten sind Primärschlüssel), wobei nur die Datensätze mit dem Minimalwert in der zweiten Spalte beibehalten werden.

Wie wird dies erreicht?

Antwort

0

Sorry, ich habe die Frage missverstanden.


SELECT col1, MIN(col2) as col2 
FROM table 
GROUP BY col1 

Natürlich gibt die Zeilen in Frage, aber vorausgesetzt, Sie die Tabelle nicht ändern können eine eindeutige Kennung hinzufügen, müssen Sie wie etwas tun:


DELETE FROM test 
WHERE col1 + '|' + col2 NOT IN 
(SELECT col1 + '|' + MIN(col2) 
FROM test 
GROUP BY col1) 

Welche funktionieren soll unter der Annahme, dass das Pipe-Zeichen erscheint nie in deinem Set.

+0

Beantwortet wenn auch nicht wirklich die Frage. OP fragt nach dem Löschen von Zeilen, nicht nach deren Auswahl –

+0

Richtig. Mein Gehirn ist noch nicht in Gang. Ich denke, die Korrektur sollte funktionieren. –

0

Idealerweise würde man in der Lage sein zu sagen:

DELETE 
FROM tbl 
WHERE (col1, col2) NOT IN (SELECT col1, MIN(col2) AS col2 FROM tbl GROUP BY col1) 

Leider, das ist nicht in T-SQL erlaubt ist, aber es ist eine proprietäre Erweiterung mit einem Doppel FROM (mit AUSSER für Klarheit):

DELETE 
FROM tbl 
FROM tbl 
EXCEPT 
    SELECT col1, MIN(col2) AS col2 FROM tbl GROUP BY col1 

allgemein gilt:

DELETE 
FROM tbl 
WHERE col1 + '|' + col2 NOT IN (SELECT col1 + '|' + MIN(col2) FROM tbl GROUP BY col1) 

Oder andere Abhilfen.

4

Dies sollte für Sie arbeiten:

; 
WITH NotMin AS 
(
    SELECT Col1, Col2, MIN(Col2) OVER(Partition BY Col1) AS TheMin 
    FROM Table1 
) 

DELETE Table1 
--SELECT * 
FROM Table1 
INNER JOIN NotMin 
ON Table1.Col1 = NotMin.Col1 AND Table1.Col2 = NotMin.Col2 
    AND Table1.Col2 != TheMin 

Dieses verwendet einen CTE (wie eine abgeleitete Tabelle, aber Reiniger) und die über Klausel als Abkürzung für weniger Code. Ich habe auch eine kommentierte Auswahl hinzugefügt, damit Sie die übereinstimmenden Zeilen sehen können (vor dem Löschen überprüfen). Dies wird in SQL 2005/2008 funktionieren.

Danke, Eric

+0

Wenn große Ergebnismengen verwendet werden, ist dies möglicherweise nicht optimal für die Leistung. Wenn das der Fall ist, können wir an einer besseren Antwort arbeiten. – Anon246

+0

Ich mag row_number() oder rank() für diese Art von Sache persönlich ... aber es ist immer noch gut und sollte akzeptiert werden. –

+0

Guter Punkt. Ich wäre daran interessiert, Ihre Lösung in dieser Hinsicht zu sehen. Ich sehe immer wieder neue Anwendungen für die Über-Klausel. :-) – Anon246

Verwandte Themen