Álv*_*lez 10 sql t-sql sql-server
如何在SQL Server中模拟MySQL的CONCAT_WS()函数?
此函数类似于CONCAT()SQL Server 2012中的函数,只是它在非NULL项之间添加了一个分隔符:
SELECT id, CONCAT_WS('; ', a, b, c, d) AS bar
FROM foo
ORDER BY id;
Run Code Online (Sandbox Code Playgroud)
| ID | BAR |
|----|------------|
| 1 | a; b; c; d |
| 2 | b; d |
| 3 | a; d |
| 4 | |
Run Code Online (Sandbox Code Playgroud)
(MySQL小提琴)
Álv*_*lez 14
我们可以使用几个技巧:
NULL值:COALESCE()他是一个有效的例子:
CREATE TABLE foo (
id INT IDENTITY(1, 1) NOT NULL,
a VARCHAR(50),
b VARCHAR(50),
c VARCHAR(50),
d VARCHAR(50),
PRIMARY KEY (id)
);
INSERT INTO foo (a, b, c, d) VALUES ('a', 'b', 'c', 'd');
INSERT INTO foo (a, b, c, d) VALUES (NULL, 'b', NULL, 'd');
INSERT INTO foo (a, b, c, d) VALUES ('a', NULL, NULL, 'd');
INSERT INTO foo (a, b, c, d) VALUES (NULL, NULL, NULL, NULL);
Run Code Online (Sandbox Code Playgroud)
SELECT id,
STUFF(
COALESCE('; ' + a, '') +
COALESCE('; ' + b, '') +
COALESCE('; ' + c, '') +
COALESCE('; ' + d, ''),
1, 2, '') AS bar
FROM foo
ORDER BY id
Run Code Online (Sandbox Code Playgroud)
| ID | BAR |
|----|------------|
| 1 | a; b; c; d |
| 2 | b; d |
| 3 | a; d |
| 4 | (null) |
Run Code Online (Sandbox Code Playgroud)
目的STUFF(..., 1, 2, '')是删除初始分隔符(2在我们的例子中是分隔符长度).
这应该适用于SQL Server 2005(可能还有早期版本).
注意:与原始CONCAT_WS()版本不同,我们的版本NULL在所有项目都返回时返回NULL.老实说,我认为这是一个更好的选择,但无论如何都应该很容易改变.
从SQL Server 2017开始, 您可以使用内置的CONCAT_WS:
CONCAT_WS
将可变数量的参数与第一个参数中指定的分隔符连接起来。(CONCAT_WS 表示用分隔符连接。)
Run Code Online (Sandbox Code Playgroud)CONCAT_WS ( separator, argument1, argument1 [, argumentN]… )NULL 值的处理
CONCAT_WS 忽略 SET CONCAT_NULL_YIELDS_NULL {ON|OFF} 设置。
如果所有参数都为空,则返回 varchar(1) 类型的空字符串。
连接期间将忽略空值,并且不添加分隔符。这有助于连接通常具有空白值的字符串的常见场景,例如第二个地址字段。参见示例 B。
如果您的方案要求使用分隔符包含空值,请参阅使用 ISNULL 函数的示例 C。
所以你可以使用你的初始查询:
SELECT id, CONCAT_WS('; ', a, b, c, d) AS bar
FROM foo
ORDER BY id;
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用这样的FOR XML子查询:
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;
Run Code Online (Sandbox Code Playgroud)
一方面,这看起来肯定比一系列COALESCE电话更复杂.另一方面,这更接近原型,因为分隔符仅指定一次.
使用的语法至少需要SQL Server 2008+,但是如果将VALUES构造函数更改为
SELECT a UNION ALL
SELECT b UNION ALL
SELECT c UNION ALL
SELECT d
Run Code Online (Sandbox Code Playgroud)
该查询也将在SQL Server 2005中运行.
对于 SQL Server 2012,您可以通过将过多的替换为COALESCEsingle来简化已接受的答案CONCAT:
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)