请考虑下面的语句:
select stuff((
select '; ' + ([FIELD_1] + [FIELD_2] + [...] + [FIELD_N])
from [TABLE] t1
where t1.[ID] = t2.[ID]
for xml path ('')
),1,1, '')
from [TABLE] t2
如果语句连接10条记录具有相同ID
,但是所有记录都没有价值(“”,或为空,而不是null
),输出为:
; ; ; ; ; ; ; ; ; ;
如果2个记录被填充,我结束了
; ; ; AAA; ; ; ; BBB;
我想在这些2案件是null
,分别为AAA; BBB
AAA; BBB
我想这样的固定它:
select stuff((
select case when [FIELD_1] <> '' then '; ' + ([FIELD_1]) else '' end
from [TABLE] t1
where t1.[ID] = t2.[ID]
for xml path ('')
),1,1, '')
from [TABLE] t2
这工作,并且是优雅足以让我当我只选择FIELD_1
。 但是,当我选择许多串连的字段( FIELD_1 + ... + FIELD_N
),这将成为相当难看快。
我究竟做错了什么? 是不是stuff()
应该照顾我的问题作为一个功能?
添加一个条件到WHERE
子句排除了所有值空字符串行
select stuff((
select '; ' + ([FIELD_1] + [FIELD_2] + [...] + [FIELD_N])
from [TABLE] t1
where t1.[ID] = t2.[ID]
and [FIELD_1] + [FIELD_2] + [...] + [FIELD_N] <> ''
for xml path ('')
),1,1, '')
from [TABLE] t2
这个答案并不意在表明一个更好的方式做查询 - 这是为了说明您正在使用的查询。
为了解决你的问题,你应该使用WHERE子句如松鼠在证明他的答案 ,而不是使用的case
表达。 选择的东西不点,你有没有用。
我看到了很多混乱的约串聚集的这种方法 - 太多的人都在使用它不理解什么是各个部件没有 - 所以这里是一个简单的解释:
有三个部分,以这种技术:
在列汇总值。 这就是在FOR XML PATH('')
一样。 在FOR XML PATH('')
将返回一个XML字符串,其中的XML标签查询的列名(或别名)。 (见cte_ForXml
和Aggregated
在下面的示例脚本列)。
添加值之间的分隔符。 这是什么';' +
';' +
一样。 它也消除了从结果中列名的XML标记 - 通过更改列名称为空字符串。 空别名是在T-SQL无效,但通过连接其它值列列名不能再被使用。
见cte_ForXml_WithAnEmptyString
和OnlyValuesAggregated
的示例脚本。
在字符串的开头删除多余的分隔符。 那是什么stuff
呢。
见cte_FirstDlimiterRemoved
和FullQuery
在示例脚本。
是什么stuff
做的是插入一个字符串到另一个字符串中,指定的index
,同时去除length
从原来的字符串charecters。 如果要插入一个空字符串,则简单地移除由所指定的部分index
和length
从原来的字符串参数。
示例脚本来说明这个字符串聚合技术的不同步骤:
DECLARE @String_Agg AS TABLE
(
s varchar(10)
)
INSERT INTO @String_Agg (s) VALUES
('1'), ('2'), ('3')
;WITH cte_ForXml(Aggregated) AS
(
SELECT s
FROM @String_Agg
FOR XML PATH('')
)
, cte_ForXml_WithAnEmptyString(OnlyValuesAggregated) AS
(
SELECT '' + s
FROM @String_Agg
FOR XML PATH('')
)
, cte_ForXmlWithADelimiter(AggregatedWithADlimiter) AS
(
SELECT ';' + s
FROM @String_Agg
FOR XML PATH('')
), cte_FirstDlimiterRemoved(FullQuery) AS
(
SELECT STUFF
(
(
SELECT ';' + s
FROM @String_Agg
FOR XML PATH('')
), 1, 1, ''
)
)
SELECT Aggregated, OnlyValuesAggregated, AggregatedWithADlimiter, FullQuery
FROM cte_ForXml
CROSS JOIN cte_ForXml_WithAnEmptyString
CROSS JOIN cte_ForXmlWithADelimiter
CROSS JOIN cte_FirstDlimiterRemoved
结果:
Aggregated OnlyValuesAggregated AggregatedWithADlimiter FullQuery
<s>1</s><s>2</s><s>3</s> 123 ;1;2;3 1;2;3