在SQL Server中使用STRING_AGG获取唯一值

gko*_*oul 7 sql sql-server string-aggregation sql-server-2017

以下查询返回如下所示的结果:

SELECT 
    ProjectID, newID.value
FROM 
    [dbo].[Data] WITH(NOLOCK)  
CROSS APPLY 
    STRING_SPLIT([bID],';') AS newID  
WHERE 
    newID.value IN ('O95833', 'Q96NY7-2') 
Run Code Online (Sandbox Code Playgroud)

结果:

ProjectID   value
---------------------
2           Q96NY7-2
2           O95833
2           O95833
2           Q96NY7-2
2           O95833
2           Q96NY7-2
4           Q96NY7-2
4           Q96NY7-2
Run Code Online (Sandbox Code Playgroud)

使用STRING_AGG以下查询中显示的新添加的功能(在SQL Server 2017中),我可以获取以下结果集。

SELECT 
    ProjectID,
    STRING_AGG( newID.value, ',') WITHIN GROUP (ORDER BY newID.value) AS 
NewField
FROM
    [dbo].[Data] WITH(NOLOCK)  
CROSS APPLY 
    STRING_SPLIT([bID],';') AS newID  
WHERE 
    newID.value IN ('O95833', 'Q96NY7-2')  
GROUP BY 
    ProjectID
ORDER BY 
    ProjectID
Run Code Online (Sandbox Code Playgroud)

结果:

ProjectID   NewField
-------------------------------------------------------------
2           O95833,O95833,O95833,Q96NY7-2,Q96NY7-2,Q96NY7-2
4           Q96NY7-2,Q96NY7-2
Run Code Online (Sandbox Code Playgroud)

我希望我的最终输出仅具有以下独特元素:

ProjectID   NewField
-------------------------------
2           O95833, Q96NY7-2
4           Q96NY7-2
Run Code Online (Sandbox Code Playgroud)

关于如何获得此结果的任何建议?如果需要,请随时从头开始进行优化/重新设计。

ttu*_*tes 14

这是我写的一个函数,它回答了 OP 标题:欢迎改进!

CREATE OR ALTER FUNCTION [dbo].[fn_DistinctWords]
(
  @String NVARCHAR(MAX)  
)
RETURNS NVARCHAR(MAX)
WITH SCHEMABINDING
AS
BEGIN
  DECLARE @Result NVARCHAR(MAX);
  WITH MY_CTE AS ( SELECT Distinct(value) FROM STRING_SPLIT(@String, ' ')  )
  SELECT @Result = STRING_AGG(value, ' ') FROM MY_CTE
  RETURN @Result
END
GO
Run Code Online (Sandbox Code Playgroud)

使用如下:

SELECT dbo.fn_DistinctWords('One Two      Three Two One');
Run Code Online (Sandbox Code Playgroud)


Joh*_*van 8

DISTINCT在合并结果之前,请在子查询中使用关键字删除重复项:SQL Fiddle

SELECT 
ProjectID
,STRING_AGG(value, ',') WITHIN GROUP (ORDER BY value) AS 
NewField
from (
    select distinct ProjectId, newId.value 
    FROM [dbo].[Data] WITH(NOLOCK)  
    CROSS APPLY STRING_SPLIT([bID],';') AS newID  
    WHERE newID.value IN (   'O95833' , 'Q96NY7-2'  )  
) x
GROUP BY ProjectID
ORDER BY ProjectID
Run Code Online (Sandbox Code Playgroud)

  • 更新了投票给 DISTINCT 的链接:https://feedback.azure.com/d365community/idea/0e8fa860-7c25-ec11-b6e6-000d3a4f0da0 (8认同)
  • 请在此处为 DISTINCT 投票:https://feedback.azure.com/forums/908035-sql-server/suggestions/35243533-support-distinct-for-string-agg (6认同)
  • 附:文档中的一些评论要求对此函数提供“distinct”关键字支持;所以也许微软会考虑在未来的版本中添加这样的功能:https://learn.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-2017 (2认同)

Gor*_*off 7

您可以distinct在用于的子查询中使用apply

SELECT d.ProjectID,
       STRING_AGG(  newID.value, ',') WITHIN GROUP (ORDER BY newID.value) AS 
NewField
FROM [dbo].[Data] d CROSS APPLY
     (select distinct value
      from STRING_SPLIT(d.[bID], ';') AS newID 
     ) newID
WHERE newID.value IN (   'O95833' , 'Q96NY7-2'  ) 
group by projectid;
Run Code Online (Sandbox Code Playgroud)


Dom*_*rda 5

这是我对 @ttugates 的改进,使其更加通用:

CREATE OR ALTER FUNCTION [dbo].[fn_DistinctList]
(
  @String NVARCHAR(MAX),
  @Delimiter char(1)
)
RETURNS NVARCHAR(MAX)
WITH SCHEMABINDING
AS
BEGIN
  DECLARE @Result NVARCHAR(MAX);
  WITH MY_CTE AS ( SELECT Distinct(value) FROM STRING_SPLIT(@String, 
@Delimiter)  )
  SELECT @Result = STRING_AGG(value, @Delimiter) FROM MY_CTE
  RETURN @Result
END
Run Code Online (Sandbox Code Playgroud)