SQL Server的CONCAT_WS()

SQL Server的CONCAT_WS(),sql,sql-server,tsql,Sql,Sql Server,Tsql,如何在SQL Server中模拟MySQL的功能 此函数与类似,只是在非空项之间添加了分隔符: SELECT id, CONCAT_WS('; ', a, b, c, d) AS bar FROM foo ORDER BY id; | ID |条| |----|------------| |1 | a;BCd| |2 | b;d| |3 | a;d| | 4 | | ()我们可以使用几个技巧: 要跳过NULL值: 为避免拖尾分隔符:在每个项目之前添加分隔符,然后用例

如何在SQL Server中模拟MySQL的功能

此函数与类似,只是在非空项之间添加了分隔符:

SELECT id, CONCAT_WS('; ', a, b, c, d) AS bar
FROM foo
ORDER BY id;
| ID |条|
|----|------------|
|1 | a;BCd|
|2 | b;d|
|3 | a;d|
|  4 |            |

()

我们可以使用几个技巧:

  • 要跳过
    NULL
    值:
  • 为避免拖尾分隔符:在每个项目之前添加分隔符,然后用例如
他是一个:

选择id,
东西(
结合(';'+a')+
结合(';'+b')+
结合(';'+c')+
结合(';'+d',),
1,2'')作为条形图
来自富
按id订购
| ID |条|
|----|------------|
|1 | a;BCd|
|2 | b;d|
|3 | a;d|
|4 |(空)|
STUFF(…,1,2',)
的目的是删除初始分隔符(
2
是本例中的分隔符长度)

这应该适用于SQLServer2005(可能还有更早的版本)


注意:与原始的
CONCAT_WS()
不同,当所有项目都
NULL
时,我们的版本返回
NULL
。老实说,我认为这是一个更好的选择,但无论如何都应该很容易改变。

另一种方法是:

SELECT
  id,
  bar = STUFF(
    (
      SELECT '; ' + v
      FROM (VALUES (a), (b), (c), (d)) AS v (v)
      FOR XML PATH (''), TYPE
    ).value('.[1]', 'varchar(max)'),
    1, 2, ''
  )
FROM foo
ORDER BY id;
一方面,这看起来肯定比一系列联合调用更复杂。另一方面,这更接近于原型,因为分隔符只指定一次

使用的语法至少需要SQL Server 2008+,但如果值构造函数更改为

SELECT a UNION ALL
SELECT b UNION ALL
SELECT c UNION ALL
SELECT d

查询也将在SQLServer2005中运行。

我使用FORXMLPATH进行查询
可以使用union(union ALL)代替值;这有一个附加值,即它仍然可以在SQLServer2005上工作(我们公司仍然必须支持它),并且您可以删除空值

DECLARE @in_SearchTerm1 nvarchar(100) 
DECLARE @in_SearchTerm2 nvarchar(100) 
DECLARE @in_SearchTerm3 nvarchar(100) 
DECLARE @in_SearchTerm4 nvarchar(100) 

SET @in_SearchTerm1 = N'a'
SET @in_SearchTerm2 = N''
SET @in_SearchTerm3 = N'c'
SET @in_SearchTerm4 = N''

SELECT 
    COALESCE
    (
        STUFF
        (
            (
                SELECT ' / ' + RPT_SearchTerm AS [text()]
                FROM 
                (
                                  SELECT NULLIF(@in_SearchTerm1, N'') AS RPT_SearchTerm, 1 AS RPT_Sort 
                        UNION ALL SELECT NULLIF(@in_SearchTerm2, N'') AS RPT_SearchTerm, 2 AS RPT_Sort  
                        UNION ALL SELECT NULLIF(@in_SearchTerm3, N'') AS RPT_SearchTerm, 3 AS RPT_Sort 
                        UNION ALL SELECT NULLIF(@in_SearchTerm4, N'') AS RPT_SearchTerm, 4 AS RPT_Sort 
                ) AS tempT 
                WHERE RPT_SearchTerm IS NOT NULL 
                ORDER BY RPT_Sort 
                FOR XML PATH(N''), TYPE 
            ).value('.', 'nvarchar(MAX)') 
            ,1
            ,3
            ,N''
        )
        ,N''
    ) AS RPT_SearchTerms 
注意nvarchar的使用-停止使用varchar
为了保持顺序,您还必须对其进行排序


那么这是做什么的:

目标:
在报告中的4个单独过滤器中输入4个搜索词
在报告中显示这4个搜索词,并通过
'/'
连接
如果搜索项为空,则不应存在
'/'

应按顺序显示,即term1/term2/term3/term4,而不是例如term4/term2/term3/term1

如何:
因此,将4个搜索词合并,并添加一个排序值以保持顺序

从联合中选择搜索词和分隔符(separator+null=null)

按RPT_排序订购

现在选择诱惑中的所有值(分隔符+文本)到一个XML文件(
用于XML
),其中所有值都是带有空标记名的XML元素(
PATH(N')
),并选择值XML文本(
作为[text()]
)(aka element.innerXML)

将该结果作为XML元素(
类型
)获取,并检索该XML元素的内部文本字符串(
值('.','nvarchar(MAX)
)(也称为XML解码)

最后,删除前导的“/”(
STUFF(var,1,3,N)”)

这在原则上与

CONCAT_WS(' / ', @in_SearchTerm1, @in_SearchTerm2, @in_SearchTerm3, @in_SearchTerm4)
现在添加nullif

CONCAT_WS(' / ', NULLIF(@in_SearchTerm1, '') , NULLIF(@in_SearchTerm2, ''), NULLIF(@in_SearchTerm3, ''), NULLIF(@in_SearchTerm4, ''))
你就在那里


这就是您仍然能够在SQL Server中执行CONCAT_WS的方式…

从SQL Server 2017开始,您可以使用内置的:

CONCAT\u WS

使用第一个参数中指定的分隔符连接可变数量的参数。(CONCAT_WS表示使用分隔符连接。)

空值的处理

CONCAT_WS忽略设置CONCAT_NULL_生成_NULL{ON | OFF}设置

如果所有参数都为null,则将显示varchar(1)类型的空字符串 返回

在连接过程中忽略空值,并且不添加 分隔符。这有助于实现连接的常见场景 通常具有空白值的字符串,例如第二个地址字段。 见例B

如果您的场景要求在分隔符中包含空值, 请参见使用ISNULL函数的示例C

因此,您可以使用初始查询:

SELECT id, CONCAT_WS('; ', a, b, c, d) AS bar
FROM foo
ORDER BY id;

我知道这是一篇老文章,但我是同一期来的

我只是使用CONCAT()函数来实现这一点

我在各个字段中保存了地址行,我想连接所有行以创建地址

我发现CONCAT()函数可以处理NULL并用空字符串替换它。 另外,如果任何加NULL的值都是NULL

所以我使用了常规的CONCAT()函数,并在每个地址行的末尾添加了空格,所以如果该行为NULL,那么combine输出为NULL

SELECT 
    CONCAT(Address01 + ' ', Address02 + ' ', Address03 + ' ', Address04) AS Address 
FROM myTable

对于SQL Server 2012,您可以将过多的
COALESCE
替换为单个:

a | b | c | d | cat
-----+------+------+------+-----------
空|空|空|空|空
空|空|空| d | d
空|空| c |空| c
空|空| c | d | c;d
空| b |空|空| b
空| b |空| d | b;d
空| b | c |空| b;c
空| b | c | d | b;c;d
a |空|空|空| a
a | NULL | NULL | d | a;d
a | NULL | c | NULL | a;c
a | NULL | c | d | a;c;d
a | b | NULL | NULL | a;b
a | b | NULL | d | a;b;d
a | b | c | NULL | a;b;c
a | b | c | d | a;b;c;d

我问这个问题是为了自己回答这个问题,并向任何人提供信息。(很抱歉,如果我找不到合适的问题。)我很乐意投票/接受其他有更好提示的答案。这与Andrey M的答案不同吗?(对不起,我已经三年没看这个了,我的头脑还没有完全成形。)@阿尔瓦罗·冈萨雷斯:我从谷歌找到了一个明确的答案。不幸的是,我没有向上滚动,所以我没有看到它。至于区别:是的
CONCAT_WS ( separator, argument1, argument1 [, argumentN]… ) 
SELECT id, CONCAT_WS('; ', a, b, c, d) AS bar
FROM foo
ORDER BY id;
SELECT 
    CONCAT(Address01 + ' ', Address02 + ' ', Address03 + ' ', Address04) AS Address 
FROM myTable
WITH tests(a, b, c, d) AS (
    SELECT NULL, NULL, NULL, NULL UNION
    SELECT NULL, NULL, NULL,  'd' UNION
    SELECT NULL, NULL,  'c', NULL UNION
    SELECT NULL, NULL,  'c',  'd' UNION
    SELECT NULL,  'b', NULL, NULL UNION
    SELECT NULL,  'b', NULL,  'd' UNION
    SELECT NULL,  'b',  'c', NULL UNION
    SELECT NULL,  'b',  'c',  'd' UNION
    SELECT  'a', NULL, NULL, NULL UNION
    SELECT  'a', NULL, NULL,  'd' UNION
    SELECT  'a', NULL,  'c', NULL UNION
    SELECT  'a', NULL,  'c',  'd' UNION
    SELECT  'a',  'b', NULL, NULL UNION
    SELECT  'a',  'b', NULL,  'd' UNION
    SELECT  'a',  'b',  'c', NULL UNION
    SELECT  'a',  'b',  'c',  'd'
)
SELECT a, b, c, d,
STUFF(CONCAT(
    '; ' + a,
    '; ' + b,
    '; ' + c,
    '; ' + d
), 1, 2, '') AS cat
FROM tests