递归连接 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

*/