2016-09-16 78 views
0

我有一个SQL表,其中包含一些冗余数据,如下所示。 (SQL Server 2012中)从SQL Server中删除重复的行表

ColumnA(varchar) | ColumnB(varchar) 
---------------- | --------------- 
name1   | name2 
name3   | name4 
name2   | name1 
name5   | name6 

,我需要选择不同的数据/从该表中的行,使得它会给我造成的

ColumnA(varchar) | ColumnB(varchar) 
---------------- | --------------- 
name3   | name4 
name2   | name1 
name5   | name6 

ColumnA(varchar) | ColumnB(varchar) 
---------------- | --------------- 
name1   | name2 
name3   | name4 
name5   | name6 

基本上,姓名1 &如果名称2以name2 & name1的形式出现(不管它们所在的列的顺序如何),则应将name2视为唯一。

我不知道如何根据字符串在不同列中相等来过滤行。

有人可以帮助我吗?

回答

1

您可以用逻辑删除的数据是这样的:

delete from t 
    where t.columnB > t.columnA and 
      exists (select 1 
        from t t2 
        where t2.columnA = t.columnB and t2.columnB = t.columnA 
       ); 

如果你不想真正删除的记录,而只是想返回没有重复的结果集,你可以使用一个类似的查询:

select t.columnA, t.columnB 
from t 
where t.columnA < t.columnB 
union all 
select t.columnA, t.columnB 
from t 
where t.columnA > t.columnB and 
     not exists (select 1 
        from t t2 
        where t2.columnA = t.columnB and t2.columnB = t.columnA 
       ); 
+0

所以一个细微差别如果删除所有重复如果测试数据实际上重复name1 name2和name2 name1所以两个在数据集中表示两次这些语句不会删除一组这些重复 – Matt

+0

@Matt。 。 。似乎很清楚,OP的意图是删除“重复”,其中定义为两列中的值是相反的:*“基本上,name1和name2应该被认为是唯一的,如果它以name2&name1出现(不管它们所在列的顺序如何)。“* –

1
with TabX as(
select 'name1' as ColumnA, 'name2' as ColumnB 
union all 
select 'name3' as ColumnA, 'name4' as ColumnB 
union all 
select 'name2' as ColumnA, 'name1' as ColumnB 
union all 
select 'name5' as ColumnA, 'name6' as ColumnB 
) 

select min(ColumnA) as ColumnA,max(ColumnB) as ColumnB 
    from tabX 
group by case when ColumnA > ColumnB then ColumnA+ColumnB else ColumnB+ColumnA end 
+0

伟大的答案迈克! – Matt

0
;WITH cte AS (
    SELECT * 
     ,ROW_NUMBER() OVER (PARTITION BY 
      CASE WHEN ColumnA < ColumnB THEN ColumnA + ColumnB ELSE ColumnB + ColumnA END 
      ORDER BY (SELECT 0)) as RowNumber 
    FROM 
     @Table 
) 

DELETE FROM cte 
WHERE 
    RowNumber > 1 

如果要选择,而不是删除其更改为

SELECT * FROM cte WHERE RowNumber = 1 

或者你也可以使用类似于@mike的方法只是用DISTINCT直case语句来获得独特的组合:

SELECT DISTINCT 
    CASE WHEN ColumnA < ColumnB THEN ColumnA ELSE ColumnB END as ColumnA 
    ,CASE WHEN ColumnA < ColumnB THEN ColumnB ELSE ColumnA END as ColumnB 
FROM 
    @Table 

下面是一些测试数据:

DECLARE @Table AS TABLE (ColumnA VARCHAR(10),ColumnB VARCHAR(10)) 
INSERT INTO @Table VALUES 
('name1','name2') 
,('name3','name4') 
,('name2','name1') 
,('name2','name1') 
,('name5','name6') 
,('name1','name2') 
0

这里有一个简单的方法来获得完全清晰的一组行(根据您的欺骗标准):

select t.columnA, t.columnB 
from (
    select t.columnA, t.columnB, 
    row_number() over (
     partition by 
      case when t.columnA >= t.columnB then t.columnA + t.columnB 
      else t.columnB + t.columnA end 
     order by t.columnA) as rseq 
     /* order of "dupes" decided above, only first one gets rseq = 1 */ 
    from t 
) t 
where t.rseq = 1