东西()将分离器,即使字段为空(stuff() adds separator even when f

2019-10-30 06:49发布

请考虑下面的语句:

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()应该照顾我的问题作为一个功能?

Answer 1:

添加一个条件到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


Answer 2:

这个答案并不意在表明一个更好的方式做查询 - 这是为了说明您正在使用的查询。

为了解决你的问题,你应该使用WHERE子句如松鼠在证明他的答案 ,而不是使用的case表达。 选择的东西不点,你有没有用。

我看到了很多混乱的约串聚集的这种方法 - 太多的人都在使用它不理解什么是各个部件没有 - 所以这里是一个简单的解释:

有三个部分,以这种技术:

  1. 在列汇总值。 这就是在FOR XML PATH('')一样。 在FOR XML PATH('')将返回一个XML字符串,其中的XML标签查询的列名(或别名)。 (见cte_ForXmlAggregated在下面的示例脚本列)。

  2. 添加值之间的分隔符。 这是什么';' + ';' +一样。 它也消除了从结果中列名的XML标记 - 通过更改列名称为空字符串。 空别名是在T-SQL无效,但通过连接其它值列列名不能再被使用。
    cte_ForXml_WithAnEmptyStringOnlyValuesAggregated的示例脚本。

  3. 在字符串的开头删除多余的分隔符。 那是什么stuff呢。
    cte_FirstDlimiterRemovedFullQuery在示例脚本。

是什么stuff做的是插入一个字符串到另一个字符串中,指定的index ,同时去除length从原来的字符串charecters。 如果要插入一个空字符串,则简单地移除由所指定的部分indexlength从原来的字符串参数。

示例脚本来说明这个字符串聚合技术的不同步骤:

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


文章来源: stuff() adds separator even when fields are empty