使用 stuff 函数和 xml 路径避免重复

Avoiding duplicates using stuff function and for xml path

我在使用具有填充功能的 mysql 服务器时遇到重复问题。数据库有几百万条记录,使用distinct是不可能的(似乎查询甚至没有处理)。

这是我的数据库结构:

PersonID    Freetext    Importance
PersonID    Freetext    Importance
PersonID    Freetext    Importance
PersonID    Freetext    Importance
PersonID    Freetext    Importance

我一直在为此查询使用以下结构。查询工作正常(关于 stuff 函数),但它 returns 重复。例如,如果有五个相同的 ID,则查询 returns 五行:

SELECT PersonID, Importance, Freetext = STUFF(
             (SELECT '~' + Freetext
              FROM TABLE t1
              WHERE t1.PersonID = t2.PersonID
              FOR XML PATH (''))
             , 1, 1, '') from TABLE t2
group By PersonID, Importance
order by Importance

如何避免这种情况?

我想将属于同一个 PersonID 的所有自由文本塞到一行中,对填充进行排序,以便最重要的行首先塞入自由文本。

只是猜测(在不知道源数据或不知道源数据的情况下无法确定这会得到所需的结果),但是如果您希望 FOR XML PATH 按重要性顺序列出值(从小到大),你需要移动 ORDER BY:

SELECT PersonID, [Freetext] = STUFF(
       (SELECT '~' + Freetext
          FROM dbo.[TABLE] AS t1
          WHERE t1.PersonID = t2.PersonID
          ORDER BY Importance
          FOR XML PATH(''), TYPE
       ).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, '') 
FROM dbo.[Table] AS t2
GROUP BY PersonID;

如果您想以某种方式包含重要性,则需要将其与自由文本连接起来;它在外部查询或分组依据中没有意义(按重要性分组实际上是导致重复项的原因)。

如果您需要防止自由文本出现重复值,则需要在子查询中添加分组。但这也变得复杂了;如果您有两个相同的自由文本值但输入的重要性不同怎么办?你舍弃重要性高的还是低的?

回到最初的问题,在 SQL Server 2017 及更高版本上,您可以使用更简单(更高效)的结构:

SELECT PersonID,  
       [Freetext] = STRING_AGG([Freetext],'~') 
                    WITHIN GROUP (ORDER BY Importance)
  FROM dbo.[Table]
  GROUP BY PersonID;