删除重复记录
Delete of duplicate records
我有一个 table ,我想根据两列(id 和角色)识别重复记录,我使用第三列(单位)来 select 记录的子集分析并在其中进行删除。下面是 table 和几行示例数据:
id | role | unit
----------------
946| 1001 | 1
946| 1002 | 1
946| 1003 | 1
946| 1001 | 2
946| 1002 | 2
900| 1001 | 3
900| 1002 | 3
900| 1001 | 3
单元 1 和单元 2 的分析应该确定要删除的两行 946/1001 和 946/1002。删除标记为 unit 1 或 2 的行并不重要。在后续步骤中,我会将标记为 unit=2 的所有记录更新为 unit=1.
我有一个 select 语句能够识别要删除的行:
SELECT * FROM (SELECT
unit,
id,
role,
ROW_NUMBER() OVER (
PARTITION BY
id,
role
ORDER BY
id,
role
) row_num
FROM thetable WHERE unit IN (1,2) ) as x
WHERE row_num > 1;
这个查询会给出这个结果:
id | role | unit
----------------
946| 1001 | 2
946| 1002 | 2
现在我想将它与DELETE结合起来删除已识别的记录。我已经非常接近(我相信)这个声明:
DELETE FROM thetable tp1 WHERE EXISTS
(SELECT
unit,
id,
role,
ROW_NUMBER() OVER (
PARTITION BY
id,
role
ORDER BY
id,
role
) as row_num
FROM
thetable tp2
WHERE unit IN (1,2) AND
tp1.unit=tp2.unit AND
tp1.role=tp2.role AND
tp1.id=tp2.id AND row_num >1
)
但是,row_num 未被识别为列。那么我应该如何修改这条语句来删除这两条标识的记录呢?
您可以这样表述:
delete from thetable t
where t.unit > (
select min(t1.unit)
from thetable t1
where t1.id = t.id and t1.role = t.role
)
这似乎是解决赋值的一种简单方法,基本上可以表述为:删除存在另一行且具有较小 unit
和相同 id
和 role
的行。
至于您想使用 row_number()
编写的查询,我认为应该是:
delete from thetable t
using (
select t.*, row_number() over(partition by id, role order by unit) rn
from mytable t
) t1
where t1.id = t.id and t1.role = t.role and t1.unit = t.unit and t1.rn > 1
用EXISTS
很简单:
DELETE FROM thetable t
WHERE t.unit IN (1,2)
AND EXISTS (
SELECT 1 FROM thetable
WHERE (id, role) = (t.id, t.role) AND unit < t.unit
)
参见demo。
结果:
> id | role | unit
> --: | ---: | ---:
> 946 | 1001 | 1
> 946 | 1002 | 1
> 946 | 1003 | 1
> 900 | 1001 | 3
> 900 | 1002 | 3
> 900 | 1001 | 3
我有一个 table ,我想根据两列(id 和角色)识别重复记录,我使用第三列(单位)来 select 记录的子集分析并在其中进行删除。下面是 table 和几行示例数据:
id | role | unit
----------------
946| 1001 | 1
946| 1002 | 1
946| 1003 | 1
946| 1001 | 2
946| 1002 | 2
900| 1001 | 3
900| 1002 | 3
900| 1001 | 3
单元 1 和单元 2 的分析应该确定要删除的两行 946/1001 和 946/1002。删除标记为 unit 1 或 2 的行并不重要。在后续步骤中,我会将标记为 unit=2 的所有记录更新为 unit=1.
我有一个 select 语句能够识别要删除的行:
SELECT * FROM (SELECT
unit,
id,
role,
ROW_NUMBER() OVER (
PARTITION BY
id,
role
ORDER BY
id,
role
) row_num
FROM thetable WHERE unit IN (1,2) ) as x
WHERE row_num > 1;
这个查询会给出这个结果:
id | role | unit
----------------
946| 1001 | 2
946| 1002 | 2
现在我想将它与DELETE结合起来删除已识别的记录。我已经非常接近(我相信)这个声明:
DELETE FROM thetable tp1 WHERE EXISTS
(SELECT
unit,
id,
role,
ROW_NUMBER() OVER (
PARTITION BY
id,
role
ORDER BY
id,
role
) as row_num
FROM
thetable tp2
WHERE unit IN (1,2) AND
tp1.unit=tp2.unit AND
tp1.role=tp2.role AND
tp1.id=tp2.id AND row_num >1
)
但是,row_num 未被识别为列。那么我应该如何修改这条语句来删除这两条标识的记录呢?
您可以这样表述:
delete from thetable t
where t.unit > (
select min(t1.unit)
from thetable t1
where t1.id = t.id and t1.role = t.role
)
这似乎是解决赋值的一种简单方法,基本上可以表述为:删除存在另一行且具有较小 unit
和相同 id
和 role
的行。
至于您想使用 row_number()
编写的查询,我认为应该是:
delete from thetable t
using (
select t.*, row_number() over(partition by id, role order by unit) rn
from mytable t
) t1
where t1.id = t.id and t1.role = t.role and t1.unit = t.unit and t1.rn > 1
用EXISTS
很简单:
DELETE FROM thetable t
WHERE t.unit IN (1,2)
AND EXISTS (
SELECT 1 FROM thetable
WHERE (id, role) = (t.id, t.role) AND unit < t.unit
)
参见demo。
结果:
> id | role | unit
> --: | ---: | ---:
> 946 | 1001 | 1
> 946 | 1002 | 1
> 946 | 1003 | 1
> 900 | 1001 | 3
> 900 | 1002 | 3
> 900 | 1001 | 3