使用递归CTE通过条件检查将多行连接到单行

时间:2016-11-05 06:13:51

标签: sql sql-server sql-server-2008 sql-server-2012 sql-server-2008-r2

CREATE TABLE table1
(
     num INT,
     val VARCHAR(100)
);

INSERT INTO table1
VALUES (1, 'test1'), (2, 'test2'), (1, 'test3'), (1, 'test4')

CREATE TABLE table2
(
     num           INT,
     concatenation VARCHAR(1000)
)  

INSERT INTO table2
SELECT num,
       Substring((SELECT DISTINCT ',' + T2.val
                  FROM   table1 T2
                  WHERE  T1.num = T2.num
                  FOR XML PATH('')), 2, 1000000)
FROM   table1 T1
GROUP  BY num  

现在我使用查询

更新了第一条记录
UPDATE table2
SET    concatenation = 'test1,test25,test4'
WHERE  num = 1  

现在在table1

中插入更多记录
INSERT INTO table1(num,val)
VALUES (3,'test5'),(1,'test6')(1,'test1')  

现在我想用更新的行更新table2条记录而不重复。在这里,我想连接文本是否存在,并避免重复存在。

预期结果:我对table2结果的更新应该得到预期结果,如下所示

select * from table2

输出:

Num concatenation
-----------------------------------
1   test1,test25,test3,test4,test6
2   test2
3   test5

2 个答案:

答案 0 :(得分:1)

你可以打击:

;WITH SplitTable2
AS
(
    SELECT 
        A.*,
        O.splitdata 
    FROM
     (SELECT *,  cast('<X>'+replace(F.concatenation,',','</X><X>')+'</X>' as XML) as xmlfilter from @table2 F) A
     CROSS APPLY ( SELECT fdata.D.value('.','varchar(50)') as splitdata FROM A.xmlfilter.nodes('X') as fdata(D)) O 
), ResultList
AS
(
    SELECT S.num, S.splitdata AS val FROM SplitTable2 S
    UNION
    SELECT T.num, T.val FROM @table1 T
), Result
AS
(
    SELECT DISTINCT
        R.num,      
        STUFF((SELECT ',' + T2.val FROM ResultList T2 WHERE T2.num = R.num FOR XML PATH('')), 1, 1, '') val
    FROM
        ResultList R
)

SELECT * FROM Result

结果:

num         val                               
----------- ----------------------------------
1           test1,test25,test3,test4,test6
2           test2
3           test5

评论答案

;WITH PrepareVal
AS
(
    SELECT 
        T1.num ,
        T1.val
    FROM
       @table1 T1
    WHERE
        NOT EXISTS
        (
            SELECT 1 FROM @table2 T2
            WHERE
                T2.num = T1.num AND 
                ',' +  T2.concatenation + ',' LIKE '%,' + T1.val + ',%'
        )

), ResultList
AS
(
    SELECT DISTINCT
        R.num,      
        STUFF((SELECT ',' + T2.val FROM PrepareVal T2 WHERE T2.num = R.num FOR XML PATH('')), 1, 1, '') val
    FROM
        PrepareVal R
), Result
AS
(
    SELECT 
        T2.num ,
        T2.concatenation + CASE WHEN R.val IS NOT NULL THEN ',' + R.val ELSE '' END AS concatenation    
    FROM    
        @table2 T2 LEFT JOIN 
        ResultList R ON T2.num = R.num

    UNION ALL

    SELECT 
        R.num ,
         R.val AS concatenation     
    FROM            
        ResultList R LEFT JOIN 
        @table2 T2 ON T2.num = R.num
    WHERE
        T2.num IS NULL 
)

SELECT * FROM Result

答案 1 :(得分:0)

INSERT INTO table2 SELECT num,STUFF((SELECT ',' + val FROM table1 T WHERE T1.num = T.num FOR XML PATH('') ),1,1,'') FROM   table1 T1 GROUP  BY num