2015-05-14 35 views
7

Tôi đã theo bảng SQL:Loại bỏ các hàng trùng lặp (dựa trên giá trị từ nhiều cột) từ bảng SQL

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) dạng một khóa chính cho bảng này.

Nếu bạn nhận thấy 3 hàng đầu tiên thuộc về cùng một khách hàng (Khách hàng kiểm tra), những người có ShipToCodes khác nhau: 1, 2 và 3. Tương tự như trường hợp với khách hàng thứ hai (ARACODE Customer). Mỗi khách hàng bình thường và khách hàng bình thường-2 chỉ có 1 bản ghi với một ShipToCode.

Bây giờ, tôi muốn nhận kết quả truy vấn trên bảng này, nơi tôi sẽ chỉ có 1 bản ghi cho mỗi khách hàng. Vì vậy, đối với bất kỳ khách hàng nào, nơi có hơn 1 hồ sơ, tôi muốn giữ hồ sơ có giá trị cao nhất cho ShipToCode.

tôi đã cố gắng điều khác nhau:

(1) Tôi có thể dễ dàng có được danh sách khách hàng với chỉ một bản ghi trong bảng.

(2) Với truy vấn sau đây, tôi có thể nhận danh sách tất cả khách hàng, những người có nhiều hơn một bản ghi trong bảng.

[Query-1]

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

(3) Bây giờ, để chọn đúng ShipToCode cho mỗi bản ghi được trả về bởi truy vấn trên, tôi không thể tìm ra, làm thế nào để lặp qua tất cả các bản ghi được trả về bởi truy vấn trên.

Nếu tôi làm điều gì đó như:

[Query-2]

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

Sau đó, tôi có thể nhận được các hồ sơ phù hợp với (: 00-1234567-Test khách hàng). Do đó, nếu tôi có thể sử dụng tất cả các kết quả từ truy vấn-1 trong truy vấn trên (truy vấn-2), thì tôi có thể nhận được các bản ghi đơn mong muốn cho các khách hàng có nhiều hơn một bản ghi. Điều này có thể được kết hợp với kết quả từ điểm (1) để đạt được kết quả mong muốn.

Một lần nữa, điều này có thể dễ dàng hơn cách tiếp cận mà tôi đang theo dõi. Xin vui lòng cho tôi biết làm thế nào tôi có thể làm điều này.

[Lưu ý: Tôi phải thực hiện việc này bằng cách sử dụng truy vấn SQL. Tôi không thể sử dụng các thủ tục được lưu trữ, vì tôi sẽ thực hiện điều này cuối cùng bằng cách sử dụng 'Scribe Insight', điều này chỉ cho phép tôi viết các truy vấn.]

+0

bản sao có thể có của [Cách xóa hàng trùng lặp trong máy chủ sql?] (Http://stackoverflow.com/questions/18390574/how-to-delete-duplicate-rows-in-sql-server) –

Trả lời

14

Sample SQL FIDDLE

1) Sử dụng CTE để nhận hồ sơ giá trị mã tàu tối đa dựa trên ARDivisionNo, CustomerNo cho mỗi C 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) Để Xóa việc sử dụng kỷ lục Xóa truy vấn, thay Chọn và thay đổi mệnh đề WHERE để 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

Cảm ơn rất nhiều câu trả lời và mẫu FIDDLES SQL! :) – Vikram

+0

Tất cả các câu trả lời khác được tôi bình chọn (và nhận xét của tôi bên dưới) đã giúp tôi và giải quyết được vấn đề của tôi. Tôi đánh dấu đây là một câu trả lời, vì Piyush đã nỗ lực để tạo và đăng Sample SQL FIDDLES. Tôi ước gì tôi có thể đánh dấu những người khác cũng như một câu trả lời (hoặc ít nhất là bởi Hart CO với lời giải thích), nhưng stackoverflow chỉ cho phép tôi chọn một! – Vikram

+0

Thanks..Vikram ... Hy vọng bạn có thể giải quyết vấn đề của mình !! Tôi cũng thích @Hart CO: - giải thích – HaveNoDisplayName

3

Bạn không nói rõ phiên bản của SQL Server, nhưng có lẽ ROW_NUMBER hỗ trợ:

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

Cảm ơn rất nhiều cho câu trả lời! :) – Vikram

2

Với row_number chức năng:

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

Cảm ơn rất nhiều vì câu trả lời! :) – Vikram

+0

Một chút sửa lỗi: Nó phải là 'phân vùng bằng ARDivisionNo, CustomerNo' và không phải' phân vùng bởi CustomerNo' cho ví dụ cụ thể của tôi trong câu hỏi mà tôi đã hỏi. – Vikram

3

ROW_NUMBER() là rất tốt cho việc này:

;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 

Bạn đề cập xóa các mục trùng lặp, nếu bạn muốn DELETE bạn có thể chỉ cần:

;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 

Chức năng ROW_NUMBER() gán một số cho mỗi hàng. PARTITION BY là tùy chọn, nhưng được sử dụng để bắt đầu đánh số cho mỗi giá trị trong một trường hoặc nhóm trường nhất định, ví dụ: nếu bạn PARTITION BY Some_Date thì cho mỗi giá trị ngày duy nhất, số sẽ bắt đầu tại 1. ORDER BY. việc đếm phải được thực hiện và được yêu cầu trong hàm ROW_NUMBER().

+0

Cảm ơn rất nhiều câu trả lời và giải thích chi tiết! :) – Vikram

+1

Một chút sửa lỗi: Nó phải là 'phân vùng bằng ARDivisionNo, CustomerNo' và không phải' phân vùng bởi CustomerNo' cho ví dụ cụ thể của tôi trong câu hỏi mà tôi đã hỏi. – Vikram

+0

@Vikram Cập nhật tương ứng., –

Các vấn đề liên quan