我有一个问题,我正在尝试合并并将数据从一个表合并到另一个表。
源表和目标表是相同的,除了目标需要在第一列上有主键。
数据输入和所需结果如下:
data in Desired results
c1 c2 c3 c1 c2 c3
+--+--+--+ +--+------+------+
1 A x 1 A B C x y
2 B z 2 B C z
3 A z 3 A z x y
1 A y +--+------+------+
3 A y
1 B x
2 C z
1 C x
3 A x
1 A x
+--+--+--+
我初始化表格......
CREATE TABLE s (c1 char(2), c2 char(8), C3 char(8))
INSERT INTO s VALUES
('1','A','x'), ('2','B','z'), ('3','A','z'),
('1','A','y'), ('3','A','y'), ('1','B','x'),
('2','C','z'), ('1','C','z'), ('3','A','x'),
('1','A','x')
CREATE TABLE d (c1 char(2) PRIMARY KEY, c2 char(8), C3 char(8))
我可以使用Cursor ...
来使用它DECLARE @c1 Char(2)
DECLARE @c2 char(8)
DECLARE @C3 char(8)
DECLARE cur CURSOR FOR SELECT c1, c2, C3 FROM s
OPEN cur
FETCH NEXT FROM cur INTO @c1, @c2, @C3
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE d SET
c2 = (CASE WHEN CHARINDEX(RTRIM(@c2), c2) > 0 THEN c2 ELSE SUBSTRING(RTRIM(c2) + ' ' + @c2, 1, 8) END),
c3 = (CASE WHEN CHARINDEX(RTRIM(@c3), c3) > 0 THEN c3 ELSE SUBSTRING(RTRIM(c3) + ' ' + @c3, 1, 8) END)
WHERE c1 = @c1
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO d (c1, c2, c3)
VALUES (@c1, @c2, @c3)
END
FETCH NEXT FROM cur INTO @c1, @c2, @c3
END
CLOSE cur
DEALLOCATE cur
但我无法让Merge工作...... 错误:违反PRIMARY KEY约束'PK__d__3213663B03BB8E22'。无法在对象'dbo.d'中插入重复键。重复键值为(1)。
MERGE INTO d USING s
ON (s.c1 = d.c1)
WHEN MATCHED THEN
UPDATE SET
c2 = (CASE WHEN CHARINDEX(RTRIM(s.c2), d.c2) > 0 THEN d.c2 ELSE SUBSTRING(RTRIM(d.c2) + ' ' + s.c2, 1, 8) END),
c3 = (CASE WHEN CHARINDEX(RTRIM(s.c3), d.c3) > 0 THEN d.c3 ELSE SUBSTRING(RTRIM(d.c3) + ' ' + s.c3, 1, 8) END)
WHEN NOT MATCHED THEN
INSERT (c1, c2, c3) VALUES (s.c1, s.c2, s.c3);
有没有办法比一行一行更优雅?
感谢您的帮助!
答案 0 :(得分:2)
您可以使用For XML Path
技巧来避免 RBAR 操作来连接每个组的行。
;WITH cte1
AS (SELECT DISTINCT c1,cs.c2 AS c2
FROM s AS A
CROSS apply (SELECT DISTINCT c2 + ' '
FROM s AS B
WHERE A.c1 = B.c1
FOR xml path('')) cs (c2)),
cte3
AS (SELECT DISTINCT c1,cs.c3 AS c3
FROM s AS A
CROSS apply (SELECT DISTINCT c3 + ' '
FROM s AS B
WHERE A.c1 = B.c1
FOR xml path('')) cs (c3))
SELECT A.c1,
a.c2,
b.c3
FROM cte1 A
INNER JOIN cte3 B
ON A.c1 = b.c1
答案 1 :(得分:0)
最好留给表示层
你可以使用核心子查询来连接基于c1的组c2,c3的值
您需要使用STUFF
和for xml path
来获取连接字符串
select c1, stuff( (select distinct ' ' + c2
from s
where s.c1 = outs.c1
for xml path('')), 1,1,''),
stuff( (select distinct ' ' + c3
from s
where s.c1 = outs.c1
for xml path('')), 1,1,'')
from s outs
group by outs.c1