【问题标题】:Concatenate multiple rows to single row with condition check using recursive CTE使用递归 CTE 将多行连接到单行并进行条件检查
【发布时间】:2016-11-05 06:13:51
【问题描述】:
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

【问题讨论】:

  • 那么,num=1 的预期结果将是 test1,test25,test4,test6?
  • 嗨@NEER我按照你的要求添加了预期的结果。请帮帮我。

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


【解决方案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

【讨论】:

  • 嗨,我不想拆分连接的数据。它可以是任何东西。所以我只想将table1数据与table2进行比较。如果 table1 数据中的记录不在 table2 中,那么我们需要连接,如果 table1 数据中的记录与行重复,那么我们不应该连接。你明白我的意思了吗?
【解决方案2】:
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  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-29
    • 2012-02-18
    • 2020-11-06
    • 1970-01-01
    • 2010-11-03
    • 1970-01-01
    • 2015-03-22
    • 2011-10-20
    相关资源
    最近更新 更多