我有以下查询:
WITH cteCountryLanguageMapping AS ( SELECT * FROM ( VALUES ('Spain', 'English'), ('Spain', 'Spanish'), ('Sweden', 'English'), ('Switzerland', 'English'), ('Switzerland', 'French'), ('Switzerland', 'German'), ('Switzerland', 'Italian') ) x ([Country], [Language]) ) SELECT [Country], CASE COUNT([Language]) WHEN 1 THEN MAX([Language]) WHEN 2 THEN STRING_AGG([Language], ' and ') ELSE STRING_AGG([Language], ', ') END AS [Languages], COUNT([Language]) AS [LanguageCount] FROM cteCountryLanguageMapping GROUP BY [Country]
我期望瑞士的“语言”列中的值以逗号分隔,即:
| Country | Languages | LanguageCount --+-------------+-------------------------------------------+-------------- 1 | Spain | Spanish and English | 2 2 | Sweden | English | 1 3 | Switzerland | French, German, Italian, English | 4
相反,我得到以下输出(4个值用分隔and):
and
| Country | Languages | LanguageCount --+-------------+-------------------------------------------+-------------- 1 | Spain | Spanish and English | 2 2 | Sweden | English | 1 3 | Switzerland | French and German and Italian and English | 4
我想念什么?
这是另一个示例:
SELECT y, STRING_AGG(z, '+') AS STRING_AGG_PLUS, STRING_AGG(z, '-') AS STRING_AGG_MINUS FROM ( VALUES (1, 'a'), (1, 'b') ) x (y, z) GROUP by y | y | STRING_AGG_PLUS | STRING_AGG_MINUS --+---+-----------------+----------------- 1 | 1 | a+b | a+b
这是SQL Server中的错误吗?
是的,这是SQL Server 2017的所有版本中存在的错误(tm)(截至撰写时)。它已在Azure SQL Server和2019RC1中修复。具体来说,优化程序中执行通用子表达式消除(确保我们不会计算超出必要数量的表达式)的部分会不正确地认为STRING_AGG(x,<separator>)只要有x匹配项,所有形式的表达式都是相同的,无论它们是什么<separator>,并将它们与第一个计算结果统一查询中的表达式。
STRING_AGG(x,<separator>)
x
<separator>
一种解决方法是x通过对其进行某种(近)身份转换来确保不匹配。由于我们正在处理字符串,因此串联一个空字符串将可以:
SELECT y, STRING_AGG(z, '+') AS STRING_AGG_PLUS, STRING_AGG('' + z, '-') AS STRING_AGG_MINUS FROM ( VALUES (1, 'a'), (1, 'b') ) x (y, z) GROUP by y