2015-05-14 13 views
7

ich folgende SQL-Tabelle haben:Entfernen von doppelten Zeilen (basierend auf Werten aus mehreren Spalten) aus SQL-Tabelle

AR_Customer_ShipTo

+--------------+------------+-------------------+------------+ 
| ARDivisionNo | CustomerNo | CustomerName | ShipToCode | 
+--------------+------------+-------------------+------------+ 
|   00 | 1234567 | Test Customer  |   1 | 
|   00 | 1234567 | Test Customer  |   2 | 
|   00 | 1234567 | Test Customer  |   3 | 
|   00 | ARACODE | ARACODE Customer |   1 | 
|   00 | ARACODE | ARACODE Customer |   2 | 
|   01 | CBE1EX  | Normal Customer |   1 | 
|   02 | ZOCDOC  | Normal Customer-2 |   1 | 
+--------------+------------+-------------------+------------+ 

(ARDivisionNo, CustomerNo,ShipToCode) bilden einen Primärschlüssel für diese Tabelle.

Wenn Sie bemerken, dass die ersten 3 Zeilen zum selben Kunden gehören (Testkunde), der verschiedene ShipToCodes hat: 1, 2 und 3. Ähnliches ist der Fall beim zweiten Kunden (ARACODE Kunde). Jeder von Normaler Kunde und Normaler Kunde-2 hat nur einen Datensatz mit einem einzelnen ShipToCode.

Jetzt möchte ich Ergebnis Abfrage für diese Tabelle, wo ich nur 1 Datensatz pro Kunde haben wird. Also, für jeden Kunden, wo es mehr als 1 Datensätze gibt, möchte ich den Datensatz mit dem höchsten Wert für ShipToCode behalten.

Ich habe versucht, verschiedene Dinge:

(1) I nur ein Datensatz in der Tabelle die Liste der Kunden mit leicht zu bekommen.

(2) Mit der folgenden Abfrage kann ich die Liste aller Kunden abrufen, die mehr als einen Datensatz in der Tabelle haben.

[Abfrage-1]

SELECT ARDivisionNo, CustomerNo 
FROM AR_Customer_ShipTo 
GROUP BY ARDivisionNo, CustomerNo 
HAVING COUNT(*) > 1; 

(3) Um nun für jeden Datensatz wählen Sie die richtigen ShipToCode von oben Abfrage zurückgegeben, ich bin, um herauszufinden, nicht in der Lage, wie durch alle iterieren die von obiger Abfrage zurückgegebenen Datensätze.

Wenn ich so etwas wie:

[Abfrage-2]

SELECT TOP 1 ARDivisionNo, CustomerNo, CustomerName, ShipToCode 
FROM AR_Customer_ShipTo 
WHERE ARDivisionNo = '00' and CustomerNo = '1234567' 
ORDER BY ShipToCode DESC 

Dann kann ich den entsprechenden Datensatz erhalten für (00-1234567-Test-Kunden). Wenn ich also alle Ergebnisse von Abfrage-1 in der obigen Abfrage (Abfrage-2) verwenden kann, kann ich die gewünschten einzelnen Datensätze für Kunden mit mehr als einem Datensatz abrufen. Dies kann mit den Ergebnissen von Punkt (1) kombiniert werden, um das gewünschte Endergebnis zu erzielen.

Auch dies kann einfacher sein als Ansatz, dem ich folge. Bitte lassen Sie mich wissen, wie ich das machen kann.

[Hinweis: Ich muss dies nur mit SQL-Abfragen tun. Ich kann keine Stored Procedures verwenden, da ich dieses Ding endlich mit 'Scribe Insight' ausführen werde, was mir nur erlaubt, Abfragen zu schreiben.]

+0

mögliche Duplikate von [Wie doppelte Zeilen in SQL Server zu löschen?] (Http://StackOverflow.com/Questions/18390574/How-To-Delete-duplicate-rows-in-SQL-server) –

Antwort

14

Sample SQL FIDDLE

1) Verwenden CTE, um den maximalen Wert für den Schiffscode basierend auf ARDivisionNo, CustomerNo für jedes C zu erhalten ustomers

WITH cte AS (
    SELECT*, 
    row_number() OVER(PARTITION BY ARDivisionNo, CustomerNo ORDER BY ShipToCode desc) AS [rn] 
    FROM t 
) 
Select * from cte WHERE [rn] = 1 

2) Um die Aufzeichnung Verwendung löschen Abfrage statt Wählen Sie zu Löschen und ändern Where-Klausel zu rn> 1. Sample SQL FIDDLE

WITH cte AS (
    SELECT*, 
    row_number() OVER(PARTITION BY ARDivisionNo, CustomerNo ORDER BY ShipToCode desc) AS [rn] 
    FROM t 
) 
Delete from cte WHERE [rn] > 1; 

select * from t; 
+0

Vielen Dank für die Antwort und die Probe SQL FIDDLES! :) – Vikram

+0

Alle anderen Antworten von mir (und mein Kommentar darunter) haben mir geholfen und mein Problem gelöst. Ich markiere dies als eine Antwort, als Piyush sich Mühe gab, Sample SQL FIDDLES zu erstellen und zu veröffentlichen. Ich wünschte, ich hätte andere auch als Antwort markieren können (oder wenigstens eine von Hart CO mit Erklärung), aber stackoverflow lässt mich nur eins wählen! – Vikram

+0

Danke..Vikram ... Hoffe, dass Sie Ihr Problem lösen können !! Ich mochte auch die @Hart CO: - Erklärung – HaveNoDisplayName

3

Sie haben geben Sie die Version von SQL Server nicht, aber ROW_NUMBER wird wahrscheinlich unterstützt:

select * 
from 
(
    select ... 
    ,row_number() 
     over (partition by ARDivisionNo, CustomerNo 
      order by ShipToCode desc) as rn 
    from tab 
) as dt 
where rn = 1 
+0

Vielen Dank für die Antwort! :) – Vikram

2

Mit row_number Funktion:

SELECT * FROM(
       SELECT ARDivisionNo, CustomerNo, CustomerName, ShipToCode, 
       row_number() over(partition by CustomerNo order by ShipToCode desc) rn 
       FROM AR_Customer_ShipTo) t 
WHERE rn = 1 
+0

Vielen Dank für die Antwort! :) – Vikram

+0

Ein bisschen Korrektur: Es sollte "Partition von ARDivisionNo, CustomerNo" und nicht "Partition von CustomerNo" für mein spezielles Beispiel in der Frage, die ich fragte. – Vikram

3

ROW_NUMBER() hierfür ist groß:

;WITH cte AS (SELECT *,ROW_NUMBER() OVER(PARTITION BY ARDivisionNo,CustomerNo ORDER BY ShipToCode DESC) AS RN 
       FROM AR_Customer_ShipTo 
      ) 
SELECT * 
FROM cte 
WHERE RN = 1 

Sie erwähnen das Entfernen der Duplikate, wenn Sie DELETE möchten, können Sie einfach:

;WITH cte AS (SELECT *,ROW_NUMBER() OVER(PARTITION BY ARDivisionNo,CustomerNo ORDER BY ShipToCode DESC) AS RN 
       FROM AR_Customer_ShipTo 
      ) 
DELETE cte 
WHERE RN > 1 

Die Funktion ROW_NUMBER() weist jeder Zeile eine Nummer zu. PARTITION BY ist optional, aber verwendet, um die Nummerierung für jeden Wert in einem bestimmten Feld oder einer Gruppe von Feldern zu beginnen, dh: wenn Sie PARTITION BY Some_Date dann für jeden eindeutigen Datumswert die Nummerierung bei 1 beginnen würde. ORDER BY wird natürlich verwendet, um zu definieren, wie Das Zählen sollte gehen und ist in der ROW_NUMBER() Funktion erforderlich.

+0

Vielen Dank für die Antwort und die detaillierte Erklärung! :) – Vikram

+1

Ein bisschen Korrektur: Es sollte 'Partition von ARDivisionNo, CustomerNo' und nicht' Partition von CustomerNo' für mein spezielles Beispiel in der Frage, die ich fragte. – Vikram

+0

@Vikram entsprechend aktualisiert., –