SQL:删除重复项(略有不同)

时间:2011-12-01 18:29:23

标签: sql sql-server tsql

我问了一个类似于这个here的问题并得到了很好的答案,但事实证明以下方式是需要完成的。我已经在这个问题上工作了好几个小时,但是还没有取得太大进展。

如何从以下列方式设置的表中删除重复项?

unique_ID | worker_ID | date | type_ID

一个worker可以有多个与它们相关联的type_ID。我想在以下条件下删除:

  1. 所有类型具有相同日期的工人的重复类型 - 删除所有类型条目,但只删除一个
  2. 一个类型具有日期和另一个类型的工作者的重复类型 具有空值 - 删除具有空值的类型条目/条目
  3. 两个都具有空日期值的工人的重复类型 - 删除所有类型条目,但只删除一个
  4. 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)
    )
    

    Demo of solution

3 个答案:

答案 0 :(得分:1)

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

您也应该能够将此解决方案适用于其他情况。

答案 1 :(得分:0)

这可能比它必须要复杂得多,但如果您要查找的内容最终每个工作人员/类型/日期三元组占一行,除非日期为空并且日期不是,我认为你想要的是什么?

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

答案 2 :(得分:-1)

这是我最终提出的解决方案:

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)
)

Demo of solution