来自多个源记录的T-SQL合并

时间:2018-08-01 15:16:02

标签: sql-server tsql merge

我已经看到了几个类似的问题,但是还没有找到可以回答我问题的问题。

我有一个源表,其中包含公司的许多单独注释

CompanyName, Notes3
Company1, "spoke with someone"
Company2, "Email no longer works"
Company1, "Moved address"

我有一个目标表(vchCompanyName在这里是唯一的)

vchCompanyName, vchNotes
Company1, "started business in 2005"
Company2, null

我想结束

vchCompanyName, vchNotes
Company1, "started business in 2005
           spoke with someone
           Moved address"
Company2, "Email no longer works"

我已经尝试过此代码

WITH CTE
AS (SELECT ROW_NUMBER() OVER (PARTITION BY CompanyName, Notes3 ORDER BY CompanyName) RowNum, *
    FROM CompanyContact
    )

    merge dCompany as target
    using CTE as source
    on target.vchcompanyname = source.companyname 
    when matched and len(source.notes3)>0 and source.RowNum = 1
    then
        update set target.vchnote = vchnote + CHAR(13) + source.Notes3

但是得到错误

  

MERGE语句尝试多次更新或删除同一行。当目标行与多个源行匹配时,就会发生这种情况。 MERGE语句不能多次更新/删除目标表的同一行。优化ON子句以确保目标行最多匹配一个源行,或使用GROUP BY子句对源行进行分组。   哪个是正确的。

我也尝试过STRING_AGG,但收到未定义的UDF错误。

如何更改代码以使其反复运行?

-编辑- 我尝试了以下更新代码

    WITH CTE
AS (SELECT ROW_NUMBER() OVER (PARTITION BY CompanyName, Notes3 ORDER BY CompanyName) RowNum, *
    FROM CompanyContact
    )
    UPDATE dCompany SET vchNote = vchNote + 
    (select CHAR(13) + cc.Notes3 from CompanyContact cc 
    inner JOIN dCompany dc ON dc.vchCompanyName COLLATE database_default = LEFT(cc.CompanyName,50) COLLATE database_default
    inner join CTE on dc.vchCompanyName COLLATE database_default = LEFT(CTE.CompanyName,50) COLLATE database_default
     WHERE LEN(cc.Notes3)>0
     and RowNum = 1     
     );

但是得到错误

  

子查询返回了多个值。当子查询遵循=,!=,<,<=,>,> =或将子查询用作表达式时,不允许这样做。

1 个答案:

答案 0 :(得分:1)

@Chris Crawshaw,我将通过在源和目标表上进行“全部合并”来获取每个公司的所有注释,以解决此问题。然后,使用STUFF功能,可以很容易地将所有笔记连接到一个单元格中,同时按各个公司名称进行分组。参见下面的模型:

DECLARE @Source TABLE (CompanyName VARCHAR(20), Notes3 VARCHAR(50))
INSERT INTO @Source
SELECT 'Company1', 'spoke with someone' UNION ALL
SELECT 'Company2', 'Email no longer works' UNION ALL
SELECT 'Company1', 'Moved address'

DECLARE @Destination TABLE (vchCompanyName VARCHAR(20), vchNotes VARCHAR(500))
INSERT INTO @Destination
SELECT 'Company1', 'started business in 2005' UNION ALL
SELECT 'Company2', NULL




    ;WITH Temp AS (

    SELECT *
    FROM
    (
        SELECT *
        FROM
            @Destination D
        WHERE D.vchNotes is not null
        UNION ALL
        SELECT * 
        FROM
            @Source S  

    )h


    )

    update  D
    SET D.vchNotes=U.vchNotes

    FROM @Destination D
    LEFT JOIN(
    SELECT t2.vchCompanyName, vchNotes=STUFF((
        SELECT  ',' + vchNotes
        FROM Temp t1 where t1.vchCompanyName=t2.vchCompanyName
        FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
    FROM
        @Destination t2
    GROUP BY
        t2.vchCompanyName
        )U ON
            U.vchCompanyName=D.vchCompanyName


    --TEST--
            SELECT * 
            FROM
            @Destination