SQL: удалить дубликаты (немного другие) - PullRequest
1 голос
/ 01 декабря 2011

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

Как удалить дубликаты из таблицы, настроенной следующим образом?

unique_ID | worker_ID | date | type_ID

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

  1. Дубликаты типов для работника, у которых все типы имеют одинаковую дату - Удалить все записи типа, кроме одной
  2. Дубликаты типов для работника, где один тип имеет дату, а другой - имеет нулевое значение - Удаляет запись типа / записи с нулевым значением
  3. Дубликаты типов для работника, где оба имеют нулевые значения даты - Удалить все записи типа, кроме одной

Номер 2 - единственная проблема, с которой у меня проблема. Я думаю, у меня есть 1 и 3 работающие.

Мой код для номера 1 за запрос.

Delete from TABLENAME
WHERE unique_ID IN
(
   SELECT MAX(unique_ID)
   FROM TABLENAME
   GROUP BY worker_ID, type_ID, date
   HAVING COUNT(*) > 1
      AND date IS NOT NULL
)

Я полагал, что номер три должен быть небольшим изменением кода, используемого для номера 1.

ОБНОВЛЕНИЕ (12/8/2011) - Решение, которое я придумал для условия 2

select
  unique_ID,
  worker_ID,
  type_ID
into #validActive
from
  #tbl
where date is not null

select
  unique_ID,
  worker_ID,
  type_ID
into #nullActive
from #tbl
where date is null

Delete from #tbl where unique_ID in
(
select #nullActive.unique_ID from #validActive join #nullActive on #validActive.worker_ID = #nullActive.worker_ID
where (#validActive.worker_ID = #nullActive.worker_ID and #validActive.type_ID = #nullActive.type_ID)
)

Демонстрация решения

Ответы [ 3 ]

1 голос
/ 01 декабря 2011
with cte as (
   select unique_ID, worker_ID, [date], type_ID,
   row_number() over (partition by worker_id order by isnull([date], '1753-01-01') desc) as [rn]
   from your_table
)
delete cte where [rn] <> 1

Вы сможете адаптировать это решение и к другим вашим случаям.

0 голосов
/ 07 декабря 2011

Вот решение, которое я в итоге придумал:

select
  unique_ID,
  worker_ID,
  type_ID
into #validActive
from
  #tbl
where date is not null

select
  unique_ID,
  worker_ID,
  type_ID
into #nullActive
from #tbl
where date is null

Delete from #tbl where unique_ID in
(
select #nullActive.unique_ID from #validActive join #nullActive on #validActive.worker_ID = #nullActive.worker_ID
where (#validActive.worker_ID = #nullActive.worker_ID and #validActive.type_ID = #nullActive.type_ID)
)

Демонстрация решения

0 голосов
/ 01 декабря 2011

Это может быть гораздо сложнее, чем должно быть, но это поможет, если то, что вы ищете, заканчивается одной строкой на триплет работник / тип / дата, за исключением случая, когда дата равна нулюдата не, что я думаю, что вы хотели?

with maxDate AS (
SELECT worker_ID, type_id, MAX(date) as maxDate 
FROM Table
GROUP BY worker_ID, type_ID
)
DELETE x
FROM Table x
JOIN (
SELECT unique_ID
, row_number() OVER (PARTITION BY w.worker_ID, w.type_ID, COALESCE(date, maxDate) ORDER BY date DESC) AS rowNumber
FROM Table w
JOIN maxDate m
ON w.worker_id = m.worker_id
AND w.type_id = m.type_id
) y
ON x.unique_id = y.unique_id
WHERE y.rowNumber <> 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...