根据匹配行

时间:2016-06-10 19:49:37

标签: sql sql-server

我有一个数据集,其中包含基于某些字段被视为重复的行。我需要匹配重复的行,评估不匹配的字段,并标记其中一个进行删除。样本表是:

ID  Col1    Col2    Col3
1   A       B       CC
2   A       B       DD
3   E       F       GG
4   E       F       HH

所以我需要识别第1行和第1行。 2作为基于Col1和Col2匹配的重复项,并比较Col3字段,最终标记第1行或第2行以进行删除。第3行和第3行也是如此。 4.此表完全由与Col1和Col2中的至少一个其他行匹配的行组成。

我的第一个想法是加入自己,将行压缩成这种格式:

t1.ID   t2.ID   t1.Col1 t1.Col2 TableOneCol3    TableTwoCol3
1       2       A       B       CC              DD
3       4       E       F       GG              HH

然后,对每行评估TableOneCol3和TableTwoCol3会很简单。 我试图通过自我加入来做到这一点:

select t1.ID, t2.ID, t1.Col1, t1.Col2, t1.Col3 as TableOneCol3, t2.col3 as TableTwoCol3
    into #temptable
from tableOne t1
    join tableTwo t2
where t1.Col1 = t2.Col2 
and t1.Col2 = t2.Col2 
and t1.ID <> t2.ID

但当然这并不能删除重复项 - 只需将重复的字段信息添加到每一行。

我走了旋转数据的道路 - 但我最终得到了类似的结果 - 我也重复了这些重复项。
我挖掘了SO,但不确定我是否具有我需要做的特定词语(公认的模糊标题可能是一个赠品 - 为此道歉)。我发现了许多将数据展平为单列和枢轴的示例,但没有任何可以压平成对行并从结果集中删除其中一行的内容。

我不确定自己是否会走错路。看来我需要在先前评估的内容中评估每一行 - 但我不知道如何在不使用游标的情况下执行此操作。

2 个答案:

答案 0 :(得分:1)

目前还不清楚你要做什么。我把一些快速的想法放在一起, 可能 就是你想做的事。

if OBJECT_ID('tempdb..#Something') is not null
    drop table #Something

create table #Something
(
    ID int
    , Col1 char(1)
    , Col2 char(1)
    , Col3 char(2)
)

insert #Something
(
    ID
    , Col1
    , Col2
    , Col3
)
VALUES
(1, 'A', 'B', 'CC'),
(2, 'A', 'B', 'DD'),
(3, 'E', 'F', 'GG'),
(4, 'E', 'F', 'HH');

with SortedResults as
(
    select *
        , ROW_NUMBER() over(partition by Col1, Col2 order by Col3) as RowNum
    from #Something
)

delete SortedResults 
where RowNum > 1

select *
from #Something;

--OR maybe you want to cross tab the data???

drop table #Something

GO

create table #Something
(
    ID int
    , Col1 char(1)
    , Col2 char(1)
    , Col3 char(2)
)

insert #Something
(
    ID
    , Col1
    , Col2
    , Col3
)
VALUES
(1, 'A', 'B', 'CC'),
(2, 'A', 'B', 'DD'),
(3, 'E', 'F', 'GG'),
(4, 'E', 'F', 'HH');

with SortedResults as
(
    select *
        , ROW_NUMBER() over(partition by Col1, Col2 order by Col3) as RowNum
    from #Something
)

select 
    MAX(case when RowNum = 1 then ID end) as ID_1
    , MAX(case when RowNum = 2 then ID end) as ID_2
    , Col1
    , Col2
    , MAX(case when RowNum = 1 then Col3 end) as Col3_1
    , MAX(case when RowNum = 2 then Col3 end) as Col3_2
from SortedResults
group by
    Col1
    , Col2

答案 1 :(得分:0)

您可以使用LEAD()分析函数获得与您描述的表格类似的表格。这样做的好处是,当你的骰子大于两组时,它可以很好地工作。例如:

select
  ID,
  lead(ID) over (partition by col1, col2 order by col3) as nextId,
  Col1,
  Col2,
  Col3,
  lead(Col3) over (partition by col1, col2 order by col3) as nextCol3
into #temptable
from tableOne

结果将是

的形式
ID  nextId  Col1  Col2 Col3  nextCol3
 1      2     A     B    CC       DD
 2   NULL     A     B    DD     NULL
 3      4     E     F    GG       HH
 4   NULL     E     F    HH     NULL

如果您确信不需要处理大于2的组,那么您可以获得所需的确切表格,然后过滤出具有nextId IS NULL的行。