递归连接 sql 中的列
Recursively concat columns in sql
我有一个 table 包含如下值
╔═══╦════╦════╦══════╦══════╗
║ b ║ l1 ║ l2 ║ l3 ║ l4 ║
╠═══╬════╬════╬══════╬══════╣
║ a ║ b1 ║ c1 ║ d1 ║ e1 ║
║ d ║ x1 ║ y1 ║ null ║ null ║
╚═══╩════╩════╩══════╩══════╝
输出应该是:
╔═══════════╗
║ ab1c1d1e1 ║
║ ab1c1d1 ║
║ ab1c1 ║
║ ab1 ║
║ dx1y1 ║
║ dx1 ║
╚═══════════╝
可能吗?我在这里看到一个模式,但能够弄清楚如何去做。
P.S: 无法使用 ROLLUP,因为服务器不支持它。
使用UNION ALL
:
SELECT * FROM(
SELECT b + l1 + l2 + l3 + l4 FROM tbl UNION ALL
SELECT b + l1 + l2 + l3 FROM tbl UNION ALL
SELECT b + l1 + l2 FROM tbl UNION ALL
SELECT b + l1 FROM tbl
) AS t(a)
WHERE a IS NOT NULL
执行计划:
这是 UNPIVOT
的另一种方法,它只会扫描 table 一次:
SELECT x.a
FROM tbl t
CROSS APPLY(VALUES
(b + l1 + l2 + l3 + l4),
(b + l1 + l2 + l3),
(b + l1 + l2),
(b + l1)
) AS x(a)
WHERE a IS NOT NULL
执行计划:
编辑:这个增强的解决方案以裸字符串形式提供数据。如果这很快 - 我不知道。请让我知道...
DECLARE @tbl TABLE( b varchar(100),l1 varchar(100),l2 varchar(100),l3 varchar(100), l4 varchar(100));
INSERT INTO @tbl VALUES
('a','b1','c1','d1','e1')
,('d','x1','y1',null,null);
SELECT u.v.value('.','varchar(max)')
FROM
(
SELECT '' + b + l1 + l2 + l3 + l4 + ';' AS x
,'' + b + l1 + l2 + l3 + ';' AS x
,'' + b + l1 + l2 + ';' AS x
,'' + b + l1 + ';' AS x
FROM @tbl
FOR XML PATH(''),TYPE
) AS XMLList(x)
CROSS APPLY XMLList.x.nodes('/x') AS a(b)
CROSS APPLY(SELECT CAST('<r>' + REPLACE(a.b.value('.','varchar(max)'),';','</r><r>') + '</r>' AS XML)) AS m(n)
CROSS APPLY m.n.nodes('/r') AS u(v)
WHERE LEN(u.v.value('.','varchar(max)'))> 0
/* Result
ab1c1d1e1
ab1c1d1
ab1c1
ab1
dx1y1
dx1
*/
我有一个 table 包含如下值
╔═══╦════╦════╦══════╦══════╗
║ b ║ l1 ║ l2 ║ l3 ║ l4 ║
╠═══╬════╬════╬══════╬══════╣
║ a ║ b1 ║ c1 ║ d1 ║ e1 ║
║ d ║ x1 ║ y1 ║ null ║ null ║
╚═══╩════╩════╩══════╩══════╝
输出应该是:
╔═══════════╗
║ ab1c1d1e1 ║
║ ab1c1d1 ║
║ ab1c1 ║
║ ab1 ║
║ dx1y1 ║
║ dx1 ║
╚═══════════╝
可能吗?我在这里看到一个模式,但能够弄清楚如何去做。 P.S: 无法使用 ROLLUP,因为服务器不支持它。
使用UNION ALL
:
SELECT * FROM(
SELECT b + l1 + l2 + l3 + l4 FROM tbl UNION ALL
SELECT b + l1 + l2 + l3 FROM tbl UNION ALL
SELECT b + l1 + l2 FROM tbl UNION ALL
SELECT b + l1 FROM tbl
) AS t(a)
WHERE a IS NOT NULL
执行计划:
这是 UNPIVOT
的另一种方法,它只会扫描 table 一次:
SELECT x.a
FROM tbl t
CROSS APPLY(VALUES
(b + l1 + l2 + l3 + l4),
(b + l1 + l2 + l3),
(b + l1 + l2),
(b + l1)
) AS x(a)
WHERE a IS NOT NULL
执行计划:
编辑:这个增强的解决方案以裸字符串形式提供数据。如果这很快 - 我不知道。请让我知道...
DECLARE @tbl TABLE( b varchar(100),l1 varchar(100),l2 varchar(100),l3 varchar(100), l4 varchar(100));
INSERT INTO @tbl VALUES
('a','b1','c1','d1','e1')
,('d','x1','y1',null,null);
SELECT u.v.value('.','varchar(max)')
FROM
(
SELECT '' + b + l1 + l2 + l3 + l4 + ';' AS x
,'' + b + l1 + l2 + l3 + ';' AS x
,'' + b + l1 + l2 + ';' AS x
,'' + b + l1 + ';' AS x
FROM @tbl
FOR XML PATH(''),TYPE
) AS XMLList(x)
CROSS APPLY XMLList.x.nodes('/x') AS a(b)
CROSS APPLY(SELECT CAST('<r>' + REPLACE(a.b.value('.','varchar(max)'),';','</r><r>') + '</r>' AS XML)) AS m(n)
CROSS APPLY m.n.nodes('/r') AS u(v)
WHERE LEN(u.v.value('.','varchar(max)'))> 0
/* Result
ab1c1d1e1
ab1c1d1
ab1c1
ab1
dx1y1
dx1
*/