我有一个查询来检查表中的重复项: -
(SELECT assignment_name
FROM (SELECT xx.supervisor_stg.*,
Row_number()
over (
PARTITION BY assignment_name
ORDER BY assignment_name) AS c
FROM xx.supervisor_stg)
WHERE c > 1)
我想从这些数据中删除重复数据,但是如果有一个值,例如assignment_name' Smith'写入三次,然后应保留1个值,另外2个应删除。
当我使用以下查询时,我收到错误:
Delete From supervisor_stg
where asg_name <>(SELECT Asg_Name
FROM (SELECT xx.supervisor_stg.*,
Row_number()
over (
PARTITION BY assignment_name
ORDER BY assignment_name) AS c
FROM xx.supervisor_stg)
WHERE c > 1)
SQL Error: ORA-01427: single-row subquery returns more than one row
01427. 00000 - "single-row subquery returns more than one row"
*Cause:
*Action:
答案 0 :(得分:2)
在Oracle中,您可以从子查询中删除,例如delete from (select * from emp where empno < 10)
。嗯,这个例子很愚蠢,但你明白了。在你的情况下,这将是:
delete from
(
select *
from
(
select
s.*,
row_number() over (partition by assignment_name order by assignment_name) as rn
from xx.supervisor_stg s
)
where rn > 1
);
虽然这个应该工作,但由于某种原因,Oracle可能会发生这种情况除外。 更新:我在Oracle 11.2中尝试了这一点,Oracle给了我ORA-01752:“如果没有一个保存密钥的表,则无法从视图中删除”。因此,尽管我们只从一个表中进行选择,但Oracle却以某种方式感到困惑。继续阅读并选择另一种解决方案: - )
另一种方法是删除不存在具有相同assignment_name和较低(或更高)rowid的另一个条目的每个记录。
delete from xx.supervisor_stg s
where not exists
(
select *
from xx.supervisor_stg other
where other.assignment_name = s.assignment_name
and other.rowid < s.rowid
);
您可以使用与NOT EXISTS
不相关的子查询,而不是使用NOT IN
的相关子查询,其中您拥有集合中的所有最小(或最大)rowid,并删除所有其他。
delete from xx.supervisor_stg
where rowid not in
(
select min(rowid)
from xx.supervisor_stg
group by assignment_name
);
关于你自己的删除声明:
<>
替换为NOT IN
。<>
与WHERE c > 1
结合使用是没有意义的,因为后者会为您提供删除记录而不是保留的记录。制作此IN
(而非NOT IN
)或制作WHERE c = 1
。你会得到:
Delete From supervisor_stg
Where rowid In
(
SELECT rowid
FROM
(
SELECT
xx.supervisor_stg.*,
Row_number() over (PARTITION BY assignment_name ORDER BY assignment_name) AS c
FROM xx.supervisor_stg
)
WHERE c > 1
);
过于复杂。如图所示,您可以使用简单聚合(min(rowid) / group by assignment_name
)。您可以使用row_number()
之类的窗口函数来避免像在第一次查询中那样读取表格两次。在您的查询中,您仍在阅读该表两次,一次查找要保留的记录,然后再次查找要删除的记录。
答案 1 :(得分:0)
;WITH numbered AS (
SELECT ROW_NUMBER() OVER(PARTITION BY [dupe-column-list] ORDER BY [dupe-column-list]) AS _dupe_num
FROM [table-name]
WHERE 1=1 -- any where clause if required
)
DELETE FROM numbered WHERE _dupe_num > 1;
此查询将根据您在此处添加的[dupe-column-list]字段为您的表分配行号。您可以为这些记录提供订单。 delete语句将删除所有[dupe-column-list]出现的记录(第一次出现除外)。
编辑:刚才注意到这是神谕。不确定上述内容是否适合您。以上是MSSQL。
答案 2 :(得分:0)
在Oracle中,您可以使用rowid
来实现此目的:
delete from xx.SUPERVISOR_STG
where rowid <> (select min(s2.rowid)
from xx.SUPERVISOR_STG
where s2.assignment_name = SUPERVISOR_STG.assignment_name
);