2015-05-14 4 views
7

Я следующие таблицы SQL:Удаление повторяющихся строк (на основе значений из нескольких столбцов) из таблицы 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) образуют первичный ключ для этой таблицы.

Если вы заметили, что первые 3 строки принадлежат одному клиенту (Test Customer), у которого разные ShipToCodes: 1, 2 и 3. Аналогично в случае второго клиента (клиент ARACODE). Каждый нормальный клиент и обычный клиент-2 имеет только 1 запись с одним ShipToCode.

Теперь я хотел бы получить запрос результатов в этой таблице, где у меня будет только 1 запись на одного клиента. Таким образом, для любого клиента, где есть более 1 записи, я хотел бы сохранить рекорд с наибольшим значением для ShipToCode.

Я пробовал различные вещи:

(1) можно легко получить список клиентов только один записи в таблице.

(2) Следующим запросом я могу получить список всех клиентов, у которых в таблице имеется более одной записи.

[Запрос-1]

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

(3) Теперь, для того, чтобы выбрать правильный ShipToCode для каждой записи, возвращаемой выше запроса, я не в состоянии выяснить, как перебрать все записи, возвращенные вышеуказанным запросом.

Если я что-то вроде:

[Запрос-2]

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

Тогда я могу получить соответствующую запись для (00-1234567-Test Заказчик). Следовательно, если я могу использовать все результаты запроса-1 в вышеуказанном запросе (запрос-2), тогда я могу получить желаемые отдельные записи для клиентов с более чем одной записью. Это можно объединить с результатами из пункта (1) для достижения желаемого конечного результата.

Опять же, это может быть проще, чем подход, за которым я следую. Пожалуйста, дайте мне знать, как я могу это сделать.

[Примечание: Я должен сделать это, используя только SQL-запросы. Я не могу использовать хранимые процедуры, так как я собираюсь выполнить эту вещь, наконец, используя «Scribe Insight», что позволяет мне писать запросы.]

+0

Возможный дубликат [Как удалить повторяющиеся строки в sql-сервере?] (Http://stackoverflow.com/questions/18390574/how-to-delete-duplicate-rows-in-sql-server) –

ответ

14

Sample SQL FIDDLE

1) Использование CTE, чтобы получить максимальную стоимость кода корабля на основе ARDivisionNo, CustomerNo для каждого 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) Для того, чтобы удалить использование записи Удалить запрос вместо выбора и изменения ИНЕКЕ гп> 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

Большое спасибо за ответ и образец SQL FIDDLES! :) – Vikram

+0

Все остальные ответы, высказанные мной (и мой комментарий ниже), помогли мне и решили мою проблему. Я отмечаю это как ответ, поскольку Piyush прилагал усилия для создания и публикации Sample SQL FIDDLES. Мне жаль, что я не мог пометить других тоже как ответ (или хотя бы один из Hart CO с объяснением), но stackoverflow только позволяет мне выбрать один! – Vikram

+0

Спасибо .. Викрам ... Надеюсь, вы сможете решить свою проблему! Мне также понравился @Hart CO: - объяснение – HaveNoDisplayName

3

Вы не указали версию SQL Server, но ROW_NUMBER, вероятно, поддерживается:

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

Большое спасибо за ответ! :) – Vikram

2

С row_number функции:

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

Большое спасибо за ответ! :) – Vikram

+0

Немного коррекции: для моего конкретного примера в вопросе, который я задал, это должен быть раздел «ARDivisionNo, CustomerNo», а не 'раздел CustomerNo'. – Vikram

3

ROW_NUMBER() отлично подходит для этого:

;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 

Вы упомянули удаление дубликатов, если вы хотите DELETE вы можете просто:

;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 

Функция ROW_NUMBER() присваивает номер каждой строке. PARTITION BY является необязательным, но используется для начала нумерации для каждого значения в заданном поле или группе полей, то есть: если вы PARTITION BY Some_Date, то для каждого уникального значения даты нумерация начнется с 1. ORDER BY, конечно, используется для определения того, как подсчет должен идти и требуется в функции ROW_NUMBER().

+0

Большое спасибо за ответ и подробное объяснение! :) – Vikram

+1

Немного коррекции: для моего конкретного примера в вопросе, который я задал, это должен быть раздел «ARDivisionNo, CustomerNo», а не 'раздел CustomerNo'. – Vikram

+0

@ Викрам Обновлено соответственно., –

Смежные вопросы