Sql 从具有基于除一列以外的所有列的DUP的表中删除精确DUP

Sql 从具有基于除一列以外的所有列的DUP的表中删除精确DUP,sql,teradata,Sql,Teradata,我想从保留一条记录的表中删除完全重复的记录。但是,我不能使用中间表方法,因为DUP位于除ID列之外的所有列上。例如: ID, COL1, Col2, col3, col4 The dups are on col1, col2, col3, col4 Below some samples: ID COL1 COL2 COL3 COL4 123 ABC 4RTFD FGY 12346 234 ABC 4RTFD FGY 12346 586 ABC 4RTFD FGY 123

我想从保留一条记录的表中删除完全重复的记录。但是,我不能使用中间表方法,因为DUP位于除ID列之外的所有列上。例如:

ID,
COL1,
Col2,
col3,
col4
The dups are on col1, col2, col3, col4

Below some samples:

ID  COL1 COL2  COL3 COL4
123 ABC  4RTFD  FGY  12346
234 ABC  4RTFD  FGY  12346
586 ABC  4RTFD  FGY  12346
这里只有Id列不同,其余四列是重复的。我只想保留max ID列行

我可以在这里使用什么方法

谢谢,
Amit

您可以完成许多其他人以前在SQL Server和Teradata中所做的事情,请参见此处,或者您甚至可以在没有类似CTE的情况下完成

DELETE FROM (
  SELECT ROW_NUMBER()
  OVER (PARTITION BY col1,col1,col3,col4
        ORDER BY ID DESC) rn
  FROM tbl  -- tbl is "your" table ...
) t1 WHERE rn>1

它可以在SQL上工作,还没有在teradata上测试过,但是,因为那里也有行号,所以我希望它可以工作…

尝试在所有列上将表连接到它自己,并且ID不同

    CREATE TABLE Dups
(
    ID int IDENTITY(1,1) PRIMARY KEY,
    Col1 int NOT NULL,
    Col2 date NOT NULL,
    Col3 char(1) NOT NULL,
    Col4 char(1) NOT NULL
 )
 INSERT dbo.Dups (Col1,Col2,Col3,Col4)
 VALUES ('1','20170925','A','Z'), ('1','20170925','A','Z'), ('1','20170925','A','Z'), ('2','20170925','A','Z'), ('2','20170925','A','Z'), ('2','20170925','A','Z'), ('3','20170925','A','Z');

 SELECT * FROM Dups;

 -- This solution to retain the first ID found that is duplicated...
 DELETE FROM Dups
 WHERE ID IN (
                SELECT ID
                FROM (
                        SELECT d1.ID,
                                row_number() OVER (ORDER BY d1.ID) AS DupSeq
                        FROM dbo.Dups AS d1
                        INNER JOIN dbo.Dups AS d2 ON d2.Col1 = d1.Col1 AND d2.Col2 = d1.Col2 AND d2.Col3 = d1.Col3 AND d2.Col4 = d1.Col4
                        WHERE d1.ID <> d2.ID
                    ) AS t
                WHERE DupSeq > 1
            );

 -- This solution to retain the last ID found that is duplicated...
 DELETE FROM Dups
 WHERE ID NOT IN (
                SELECT DISTINCT
                       max(t.ID) OVER(PARTITION BY t.Col1,t.Col2,t.Col3,t.Col4 ORDER BY WindowOrder) AS KeepID
                FROM (
                        SELECT d1.ID,
                                d1.Col1,
                                d1.Col2,
                                d1.Col3,
                                d1.Col4,
                                1 AS WindowOrder
                        FROM dbo.Dups AS d1
                        LEFT OUTER JOIN dbo.Dups AS d2 ON  d2.Col1 = d1.Col1 
                                                       AND d2.Col2 = d1.Col2 
                                                       AND d2.Col3 = d1.Col3 
                                                       AND d2.Col4 = d1.Col4
                                                       AND d1.ID <> d2.ID
                    ) AS t
            );


 SELECT * FROM Dups;

DROP TABLE dbo.Dups
在第一个解决方案中需要行号,因为显然ID1将匹配ID3,因此ID3也将匹配ID1

在第二种解决方案中,联接保留在外部,以保留那些不重复的值。

您可以使用相关子查询和max函数来实现所需的结果,如下所示

DELETE
FROM table1 t1
WHERE t1.Id <> (
        SELECT max(t2.Id)
        FROM table1 t2
        WHERE t1.col1 = t2.col1
            AND t1.col2 = t2.col2
            AND t1.col3 = t2.col3
            AND t1.col4 = t2.col4
        );
结果:

你可以查看演示

更新:

下面的行将添加到示例数据集中

id  col1    col2    col3    col4
----------------------------------
345 XYZ    4FTFD    FGY     12346
745 XYZ    4FTFD    FGY     12346
945 XYZ    4FTFD    FGY     12346
结果:

*注: 由于teradata在线演示工具不可用,PostgreSQL演示已被用作PostgreSQL支持的相关子查询。在本地teradata环境中也对查询进行了模拟。
这不是分组功能的简单用法吗

select max(ID) ID, COL1, COL2, COL3
from tableA
group by 2,3,4
并将其保存到新表中。如果需要从现有表中删除重复行,可以执行以下delete语句:

delete from tableA as a1
    where (
        select 1 from (
            select max(ID) ID, COL1, COL2, COL3 from tableA group by 2,3,4) a2
        where a1.ID = a2.ID
            and a1.COL1 = a2.COL1
            and a1.COL2 = a2.COL2
            and a1.COL3 = a2.COL3
         ) is null


添加一些示例表数据和预期结果-作为格式化文本而不是图像。不清楚,但您可以添加更多示例来更正您的问题。Hi jarlh,Peppe,添加了一些示例。可能重复感谢Nick,我的要求略有不同。添加了一些样本。让我看看建议的一个是否有效。啊,我知道你想保留最后一个副本并删除其余的…我将用修改后的解决方案更新我的答案。好的。非常感谢Nick!!你好,Nick,子查询中不允许获取基于顺序的聚合和顺序分析函数之类的错误!!:可能与teradata有关,在SQL Server中工作而不是在子查询中,然后将其结果插入到临时表中,并在删除的子查询中使用该结果,例如,`WHERE ID NOT in SELECT ID FROM@tentablehi Cars10m,我认为这对我来说行不通。在这里添加了一些示例。谢谢。谢谢扎鲁克,让我试试这个!!嗨@Zarruq,这不起作用,因为我想要基于Nick提到的特定分区的maxid,这给了我一个错误Teradata@user3901666:什么分区?正如我在前面提到的演示中添加了另一组示例记录,其结果与Nick的查询结果相同。另外,我已经在本地TD-DB实例上成功地模拟了teradata,您在teradata中遇到了什么错误。PFA@dnoeth:你在吗?敬请评论:-嗨Zarruq,我只需要根据所有列的分区选择最大id,不包括我需要删除所有记录的最大id。通过您的代码,我只得到了max id,这将给出子查询中不允许的基于顺序的聚合和顺序分析函数之类的错误。我已经实现了使用correlatequeryexists子句@user3901666这是真的,不允许使用有序分析函数,这个解决方案只使用分组,这是允许的。我在我的系统Teradata 14.10.07.17上测试了这段代码,它的工作原理与预期的一样。好的..谢谢@Markusn让我检查一下..会给你回复的
id   col1    col2   col3    col4
-----------------------------------
586  ABC    4RTFD   FGY     12346
945  XYZ    4FTFD   FGY     12346
select max(ID) ID, COL1, COL2, COL3
from tableA
group by 2,3,4
delete from tableA as a1
    where (
        select 1 from (
            select max(ID) ID, COL1, COL2, COL3 from tableA group by 2,3,4) a2
        where a1.ID = a2.ID
            and a1.COL1 = a2.COL1
            and a1.COL2 = a2.COL2
            and a1.COL3 = a2.COL3
         ) is null