2016-09-16 77 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