sql将两行合并为一个,相同的表。 (用第2行数据更新第1行,然后删除第2行)

时间:2014-10-07 07:32:09

标签: sql sql-server merge rows

我想将两行合并为一行,然后删除过时的行。 这是我的意思的一个小例子。

初始数据:

id | part A | part B
0  |  OK    |  NULL
1  | NULL   |  OK

将1合并为0,然后删除1,结果如下。

id | part A | part B
0  |  OK    |  OK

什么是最好的方式。必须有某种合并/合并功能,我忽略了。

提前致谢。

PS。可能与此重复:possible duplicate 但它没有得到一个好的答案。

编辑: 我正在使用MS SQL(Server 2012)

2 个答案:

答案 0 :(得分:1)

在oracle的情况下使用子查询进行条件删除。

从tablename中删除(partA | partB)=(从表名中选择partA | partB)

答案 1 :(得分:1)

这解决了你的问题 - 可能会简化它,但我把它作为一个单一陈述的挑战。

declare @t table (id int not null, A varchar(20) null,
                  B varchar(19) null, C varchar(18) null)

//Sample data expanded from question
insert into @t (id,A,B,C) values
(0,'OKA',null,'Old'),
(1,null,'OKB','New')

//Input provided - @FromID is the row we'll delete
declare @FromID int
declare @ToID int

select @FromID = 1, @ToID = 0

//The actual query
;With src as (
    select @ToID as ID,A,B,C,0 as Del from @t where id = @FromID
    union all
    select @FromID,null,null,null,1
)
merge into @t t
using (select ID,A,B,C,Del from src) s
on
    t.ID = s.ID
when matched and Del = 0 then
    update set
        A = COALESCE(s.A,t.A),
        B=  COALESCE(s.B,t.B),
        C = COALESCE(s.C,t.C)
when matched then
    delete
;

//And show the final result
select * from @t

结果是:

id          A                    B                   C
----------- -------------------- ------------------- ------------------
0           OKA                  OKB                 New

这表明NULL没有覆盖非NULL s,并且在两行都有数据的情况下,我们从我们正在删除的行中取值。


这可以通过在src CTE中构造两行来实现 - 一行包含我们要删除的行中的所有数据,除了我们将数据复制到的行{{1} }列。第二行只包含要删除ID值的行。但是,名为ID的新列中的行也不同,该列指示这是否是导致删除(Del)或更新(1)的行。

然后,在合并中,我们最终匹配两行,并使用0列来决定要采取的操作。