Удаление дубликатов на основе Group By — SQL

РЕДАКТИРОВАТЬ: я думаю, что теперь у меня есть решение, но мне нужно еще немного проверить смысл...

DELETE TBLFIRE_TEMP3 FROM TBLFIRE_TEMP3
LEFT OUTER JOIN (
   SELECT MIN(FireNo) as FireNo, ActionRef, FRADate, FIREUPRN
   FROM TBLFIRE_TEMP3 
   GROUP BY ActionRef, FRADate, FIREUPRN
) as KeepRows ON
   TBLFIRE_TEMP3.FireNo = KeepRows.FireNo
WHERE
   KeepRows.FireNo IS NULL

-############### Предыдущие комментарии ################

У меня есть таблица, в которой есть дубликаты (на основе трех столбцов). Я могу найти их и увидеть, выполнив следующие действия, а затем просто захочу удалить дубликаты (т. Е. Таким образом, все результаты count (*) равны «1»)

SELECT COUNT(*),ActionRef, FRADate, FIREUPRN
FROM TBLTempTable
GROUP BY ActionRef, FRADate, FIREUPRN

Так что я могу видеть, сколько раз встречаются эти группы. Что я хочу сделать, так это удалить дубликаты. Я пробовал следующее, но он удаляет каждую строку, даже в единственном числе:

DELETE a FROM TblTempTable a JOIN
(
  SELECT ActionRef, FRADate, FIREUPRN
    FROM TblTempTable 
   GROUP BY ActionRef, FRADate, FIREUPRN
) d 
   ON (a.ActionRef = b.ActionRef
  AND a.FRADate = b.FRADate
AND a.FIREUPRN = b.FIREUPRN)

Основываясь на кодах, которые я просмотрел в руководстве, я считаю, что я близок, но в настоящее время он удаляет все.

Ссылки: SQL- Как удалить повторяющиеся строки? GROUP BY не удаляет дубликаты

-Это MySQL, поэтому в конце концов это не актуально:

выбирать и удалять строки в группах с помощью mysql Поиск повторяющихся записей в MySQL


person indofraiser    schedule 28.04.2015    source источник
comment
Какие дбм? DELETE JOIN — это синтаксис, специфичный для продукта — он все еще нужен — или более общий синтаксис ANSI SQL?   -  person jarlh    schedule 28.04.2015
comment
Кроме того, удалить какие дубликаты? Вам нужно решить, как выбрать строки, чтобы сохранить.   -  person jarlh    schedule 28.04.2015
comment
Управление SQL Server 2014   -  person indofraiser    schedule 28.04.2015
comment
Дубликатом считается все, что имеет одинаковые ActionRef, FRADate и FireUPRN.   -  person indofraiser    schedule 28.04.2015
comment
@jarlh: это не имеет значения, поскольку строки одинаковы для любой данной группы. Он просто хочет оставить одну строку для каждой группы.   -  person Veverke    schedule 28.04.2015
comment
@Veverke, откуда мы знаем, что столбцов больше нет? Возможно, следует сохранить самые новые или самые старые строки?   -  person jarlh    schedule 28.04.2015
comment
@jarlh: действительно, хороший момент, я пропустил это.   -  person Veverke    schedule 28.04.2015


Ответы (2)


Простое решение — использовать CTE с ROW_NUMBER:

WITH Data AS
(
    SELECT RN  = ROW_NUMBER() OVER (PARTITION BY ActionRef, FRADate, FIREUPRN
                                    ORDER BY FRADate ASC),
           Cnt = COUNT(*) OVER (PARTITION BY ActionRef, FRADate, FIREUPRN),
           ActionRef, FRADate, FIREUPRN
    FROM TBLTempTable
)
DELETE FROM Data
WHERE RN > 1

Это удаляет все, кроме одного, сохраняет самый старый FRADate. Вам нужно изменить ORDER BY в ROW_NUMBER, чтобы изменить эту логику.

Одним из преимуществ CTE является то, что вы можете легко изменить его, чтобы увидеть, что вы собираетесь удалить (или обновить). Поэтому вам просто нужно заменить DELETE FROM Data на SELECT * FROM Data.

person Tim Schmelter    schedule 28.04.2015
comment
Я мог бы взять заказ FRADate, так как он является частью группы, поэтому он не имеет значения. Я использую идентификатор, поскольку что-то могло измениться в другом месте. - person indofraiser; 28.04.2015
comment
@indofraiser: я даже не понял, что это часть группы. Однако я не знал, как вы хотите сортировать, поэтому я взял первый столбец даты, который я видел. Замените его чем-то более значимым, вы также можете использовать несколько столбцов. Применяются те же правила, что и для обычного ORDER BY. - person Tim Schmelter; 28.04.2015
comment
Отлично, просто хотел уточнить :-) - person indofraiser; 28.04.2015

Также есть более простой метод для удобочитаемости:

;WITH DEDUPE AS (
SELECT ROW_NUMBER() OVER(
    PARTITION BY ActionRef, FRADate, FIREUPRN
        ORDER BY (SELECT 1)) AS RN
FROM TBLTempTable)
DELETE FROM DEDUPE
WHERE RN != 1

Мы используем именно этот сценарий на работе ежедневно. Вы можете изменить предложение ORDER BY на любой столбец, если хотите сохранить более новые строки на основе столбца даты и т. д.

person John Bell    schedule 28.04.2015