我有一条看起来像这样的路径
Subdomain1>Subdomain2>Subdomain3>Subdomain3>Subdomain5
长度是可变的,也有可能为NULL。
我怎样才能创建 5 列这样
第 1 列显示根节点,第 2 列显示根节点和下一个节点,依此类推
因此在本例中第 3 列将是 Subdomain1>Subdomain2>Subdomain3
如果路径是
Subdomain1>Subdomain2
那么第 3、4 和 4 列将为空
路径是
Subdomain1>Subdomain2>Subdomain3>Subdomain3>Subdomain5>Subdomain6
那么第 5 列将是 Subdomain1>Subdomain2>Subdomain3>Subdomain3>Subdomain5
我们正在运行 SQL Server 2016
请尝试以下利用 SQL Server XML 和 XQuery 功能的解决方案。
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (id INT IDENTITY PRIMARY KEY, _path VARCHAR(256));
INSERT INTO @tbl (_path) VALUES
('Subdomain1>Subdomain2>Subdomain3>Subdomain3>Subdomain5'),
('Subdomain1>Subdomain2');
-- DDL and sample data population, end
DECLARE @separator CHAR(1) = '>';
SELECT *
, col1 = IIF(cnt < 1, NULL, REPLACE(c.query('for $x in /root/r[position() le 1]
return data($x)').value('.', 'VARCHAR(256)'),SPACE(1),@separator))
, col2 = IIF(cnt < 2, NULL, REPLACE(c.query('for $x in /root/r[position() le 2]
return data($x)').value('.', 'VARCHAR(256)'),SPACE(1),@separator))
, col3 = IIF(cnt < 3, NULL, REPLACE(c.query('for $x in /root/r[position() le 3]
return data($x)').value('.', 'VARCHAR(256)'),SPACE(1),@separator))
, col4 = IIF(cnt < 4, NULL, REPLACE(c.query('for $x in /root/r[position() le 4]
return data($x)').value('.', 'VARCHAR(256)'),SPACE(1),@separator))
, col5 = IIF(cnt < 5, NULL, REPLACE(c.query('for $x in /root/r[position() le 5]
return data($x)').value('.', 'VARCHAR(256)'),SPACE(1),@separator))
FROM @tbl AS t
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
REPLACE(_path, @separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(c)
CROSS APPLY (SELECT c.value('count(/root/r)', 'INT')) AS t2(cnt);
输出
id | _路径 | col1 | col2 | col3 | col4 | 第5栏 |
---|---|---|---|---|---|---|
1 | 子域名1>子域名2>子域名3>子域名3>子域名5 | 子域1 | 子域1>子域2 | 子域名1>子域名2>子域名3 | 子域名1>子域名2>子域名3>子域名3 | 子域名1>子域名2>子域名3>子域名3>子域名5 |
2 | 子域1>子域2 | 子域1 | 子域1>子域2 | 空 | 空 | 空 |