【发布时间】:2019-03-03 03:53:12
【问题描述】:
我有以下疑问:
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]
我希望瑞士的 Languages 列中的值用逗号分隔,即:
| Country | Languages | LanguageCount
--+-------------+-------------------------------------------+--------------
1 | Spain | Spanish and English | 2
2 | Sweden | English | 1
3 | Switzerland | French, German, Italian, English | 4
相反,我得到以下输出(4 个值由 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 中的错误吗?
【问题讨论】:
-
似乎是一个错误,无论你如何编写 CASE,它总是返回第一个 STRING_AGG
-
这是一个优化器错误的美丽之处。更简单、更引人注目的重现:
CASE COUNT([Language]) WHEN 1234567 THEN STRING_AGG([Language], ' and ') ELSE STRING_AGG([Language], ', ') END AS [Languages](使用1234567案例)和CASE COUNT([Language]) WHEN 1234567 THEN STRING_AGG([Language], ' and ') END AS [Languages](省略ELSE——现在匹配失败,表达式变为NULL)。不管“正确”的结果应该是什么,肯定不是这样。 -
不确定这是否合适,但是....哈哈!由于这不是您缺乏知识,而不是许多人会遇到的真实情况,因此我强烈建议将问题标题更改为比通用的“未按预期工作”更准确,以最大程度地受益于全部。
-
在生成的执行计划中,第二个
STRING_AGG完全缺失,而是将表达式反弹到第一个,就好像CASE说过两次STRING_AGG([Language], ' and ')。任何后续的CASEs 也会被吸收。子表达式消除似乎发生了一些非常奇怪的事情。 -
这个错误似乎专门针对
STRING_AGG进行了调整。如果将ELSE更改为'blargh' + STRING_AGG(...),您将得到'blarghFrench and German...,因此它不正确地将第二个STRING_AGG与第一个统一起来。最简单的解决方法是将ELSE表达式更改为STRING_AGG([Language] + '', ', ')- 这会破坏 CSE,这表明存在 CSE 忽略STRING_AGG的第二个参数的错误。
标签: sql sql-server sql-server-2017 string-aggregation