2015-03-31 57 views
4

我有一個問題,我試圖將數據從一個表合併到另一個表中。在SQL中使用合併合併兩個表

除了目標需要在第一列上有主鍵之外,源表和目標表是相同的。

的數據輸入和預期的結果如下:

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

我可以得到它使用遊標工作...

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 

但我不能合併工作...
錯誤:Vi主鍵約束'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

哪個RDBMS是這樣的?請添加一個標籤來指定您是使用'mysql','postgresql','sql-server','oracle'還是'db2' - 或者其他的東西。 – 2015-03-31 18:36:47

+0

@marc_s - 語法清楚地說它是'sql server' – 2015-03-31 18:44:53

回答

2

您可以避免RBAR操作使用For XML Path技巧來連接每個組的行。

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

這是最好留給表示層,

可以使用corelated子查詢來連接C2的值,C3基礎上,集團由C1

您需要使用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