从SQL Server表

时间:2016-09-16 21:02:17

标签: sql sql-server

我有一个带有一些冗余数据的SQL表,如下所示。 (SQL Server 2012)

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

基本上,name1& name2应该被认为是唯一的,如果它作为name2&存在。 name1(不论它们所在的列的顺序如何)。

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

有人可以帮我这个吗?

4 个答案:

答案 0 :(得分: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
                 );

答案 1 :(得分: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

答案 2 :(得分: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直接表达式来获得唯一的组合:

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')

答案 3 :(得分: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