如何在多行且不带逗号的情况下使用COALESCE?


27

我正在努力实现以下目标:

California | Los Angeles, San Francisco, Sacramento
Florida    | Jacksonville, Miami

不幸的是,我正在“洛杉矶,旧金山,萨克拉曼多,杰克逊维尔,迈阿密”

我可以使用STUFF函数获得所需的结果,但是想知道是否有使用COALESCE的更干净的方法?

STATE       | CITY
California  | San Francisco
California  | Los Angeles
California  | Sacramento
Florida     | Miami
Florida     | Jacksonville 


DECLARE @col NVARCHAR(MAX);
SELECT @col= COALESCE(@col, '') + ',' + city
FROM tbl where city = 'California';
SELECT @col;

谢谢

Answers:


45

这可能是您追求的更清洁的方法。基本上,检查变量是否已初始化。如果还没有,请将其设置为空字符串,然后附加第一个城市(不带逗号)。如果有,请添加逗号,然后添加城市。

DECLARE @col nvarchar(MAX);
SELECT @col = COALESCE(@col + ',', '') + city
  FROM dbo.tbl WHERE state = 'California';

当然,这仅适用于在每个状态下填充变量。如果您一次拉出每个州的清单,那么一次就可以找到更好的解决方案:

SELECT [state], cities = STUFF((
    SELECT N', ' + city FROM dbo.tbl
    WHERE [state] = x.[state]
    FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM dbo.tbl AS x
GROUP BY [state]
ORDER BY [state];

结果:

state       cities
----------  --------------------------------------
California  San Francisco, Los Angeles, Sacramento  
Florida     Miami, Jacksonville

要在每个州内按城市名称排序:

SELECT [state], cities = STUFF((
    SELECT N', ' + city FROM dbo.tbl
    WHERE [state] = x.[state]
    ORDER BY city
    FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM dbo.tbl AS x
GROUP BY [state]
ORDER BY [state];

在Azure SQL数据库或SQL Server 2017+中,可以使用STRING_AGG()功能

SELECT [state], cities = STRING_AGG(city, N', ')
  FROM dbo.tbl
  GROUP BY [state]
  ORDER BY [state];

并按城市名称排序:

SELECT [state], cities = STRING_AGG(city, N', ') 
                         WITHIN GROUP (ORDER BY city)
  FROM dbo.tbl
  GROUP BY [state]
  ORDER BY [state];

谢谢亚伦。我当前的解决方案与您的解决方案几乎相同,除了我使用的是DISTINCT而不是GROUP BY。
user2732180

2
@ user2732180您应该使用GROUP BY,因为它更有可能对每个状态执行一次串联。例如,使用DISTINCT时,它将对加利福尼亚的每个实例应用相同的串联,然后才丢弃它所做的所有工作,以生成这些重复项。
亚伦·伯特兰

6

只是为了补充上述亚伦的答案 ...

请注意,ORDER BY仅在查询中包含最后一项可能会破坏。就我而言,我没有分组,因此不确定是否有区别。我正在使用SQL2014。就我而言,我有类似value1,value2,value3 ...的值,但变量中的结果仅为value3。


亚伦评论说:

在Connect上已至少报告了四次:

  1. 在“变量串联和按过滤器排序”结果中(如条件)
  2. (n)添加ORDER BY时从ResultSet构建varchar失败
  3. 使用CROSS APPLYs和表值函数从有序SELECT分配局部变量仅返回最后一个值
  4. 从表变量串联varchar(max)/ nvarchar(max)值时,如果通过非主键列进行过滤和排序,则可能返回错误的结果

Microsoft的示例响应:

您看到的行为是设计使然。在带有ORDER BY子句的查询中使用赋值操作(在此示例中为串联)具有未定义的行为。

该响应还引用了KB 287515:

PRB:执行计划和汇总查询的结果取决于表达式的位置

解决方案是,FOR XML PATH如果连接顺序很重要,并且当然要确保包括所有值,则使用(Aaron答案中的第二种方法)。另请参阅:

nvarchar串联/索引/ nvarchar(max)在堆栈溢出时的无法解释的行为

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.