2016-06-10 115 views
-1

我有一个数据集,其中包含基于特定字段的被视为重复的行。我需要匹配重复的行,评估不匹配的字段,并将其中的一个标记为删除。的试样台是:根据匹配行的条件识别删除/更新的行

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

所以我需要确定行1 & 2基于col1和col2上匹配重复,并比较COL3字段,最终标记无论是行1或2为删除。第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,但不知道我是否有我需要做的具体词(公认的模糊标题可能是一个赠品 - 道歉)。我发现了很多将数据展平为单列和枢轴的例子,但没有任何东西会将成对的行平坦化并将其中一个从结果集中移除。

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

+0

“你最终如何标记第1行或第2行进行删除” - 没有标准,你将无法以编程方式执行 – dbmitch

+0

有业务逻辑来评估哪一行被删除,这与问题无关。这是我正在处理的数据的一个非常简单的例子。 – pbrown

回答

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 

如果你有信心,你不需要处理大于二组,那么你可以得到你想要通过精确的表之后过滤掉,例如,具有nextId IS NULL的行。

+0

铅 - 真棒!是的,在这种情况下,我可以将表格严格限制为两个副本 - 删除空值,然后评估剩余部分以从主数据集中删除行。谢谢! – pbrown

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 
+0

我的选择是为选项1. http://rextester.com/FWCU91123 –