SQL 查询中行中多列的拆分逗号分隔值
Split comma separated values of a multiple column in row in SQL query
我有这样的数据
Code address phno
123 test1,test2,test3 123,456,789
我想要输出
Code address phno
123 test1 123
123 test2 456
123 test3 789
我的代码是这样的
declare @address VARCHAR(500) = 'test1,test2,test3', @phoneno VARCHAR(500) = '123,456,789'
select *
from STRING_SPLIT(@address, ','), STRING_SPLIT(@phoneno, ',')
但它 returns 多个值
请尝试以下解决方案。
SQL
DECLARE @tbl TABLE (Code CHAR(3), address VARCHAR(100), phno VARCHAR(100));
INSERT INTO @tbl (Code, address, phno) VALUES
('123', 'test1,test2,test3', '123,456,789');
;WITH cte1 AS
(
SELECT Code, value AS address
, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS seq
FROM @tbl
CROSS APPLY STRING_SPLIT(address, ',')
), cte2 AS
(
SELECT Code, value AS phno
, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS seq
FROM @tbl
CROSS APPLY STRING_SPLIT(phno, ',')
)
SELECT cte1.code, cte1.address, cte2.phno
FROM cte1 INNER JOIN cte2
ON cte2.seq = cte1.seq;
SQL #2, JSON 基于
;WITH rs AS
(
SELECT *
, ar1 = '["' + Replace(address, ',', '","') + '"]'
, ar2 = '["' + Replace(phno, ',', '","') + '"]'
FROM @tbl
)
SELECT Code, address.[value] AS [address], phno.[value] AS phno
FROM rs
CROSS APPLY OPENJSON (ar1, N'$') AS address
CROSS APPLY OPENJSON (ar2, N'$') AS phno
WHERE address.[key] = phno.[key];
输出
+------+---------+------+
| code | address | phno |
+------+---------+------+
| 123 | test1 | 123 |
| 123 | test2 | 456 |
| 123 | test3 | 789 |
+------+---------+------+
您可以为此使用递归 CTE:
with cte as (
select code, cast(NULL as varchar(max)) as address, cast(NULL as varchar(max)) as phno,
cast(address + ',' as varchar(max)) as rest_address, cast(phno + ',' as varchar(max)) as rest_phno, 0 as lev
from t
union all
select code, left(rest_address, charindex(',', rest_address) - 1), left(rest_phno, charindex(',', rest_phno) - 1),
stuff(rest_address, 1, charindex(',', rest_address), ''), stuff(rest_phno, 1, charindex(',', rest_phno), ''), lev + 1
from cte
where rest_address <> ''
)
select code, address, phno
from cte
where lev > 0;
Here 是一个 db<>fiddle.
如果列表中的元素可以超过 100 个,则需要 option (maxrecursion 0)
。
我有这样的数据
Code address phno
123 test1,test2,test3 123,456,789
我想要输出
Code address phno
123 test1 123
123 test2 456
123 test3 789
我的代码是这样的
declare @address VARCHAR(500) = 'test1,test2,test3', @phoneno VARCHAR(500) = '123,456,789'
select *
from STRING_SPLIT(@address, ','), STRING_SPLIT(@phoneno, ',')
但它 returns 多个值
请尝试以下解决方案。
SQL
DECLARE @tbl TABLE (Code CHAR(3), address VARCHAR(100), phno VARCHAR(100));
INSERT INTO @tbl (Code, address, phno) VALUES
('123', 'test1,test2,test3', '123,456,789');
;WITH cte1 AS
(
SELECT Code, value AS address
, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS seq
FROM @tbl
CROSS APPLY STRING_SPLIT(address, ',')
), cte2 AS
(
SELECT Code, value AS phno
, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS seq
FROM @tbl
CROSS APPLY STRING_SPLIT(phno, ',')
)
SELECT cte1.code, cte1.address, cte2.phno
FROM cte1 INNER JOIN cte2
ON cte2.seq = cte1.seq;
SQL #2, JSON 基于
;WITH rs AS
(
SELECT *
, ar1 = '["' + Replace(address, ',', '","') + '"]'
, ar2 = '["' + Replace(phno, ',', '","') + '"]'
FROM @tbl
)
SELECT Code, address.[value] AS [address], phno.[value] AS phno
FROM rs
CROSS APPLY OPENJSON (ar1, N'$') AS address
CROSS APPLY OPENJSON (ar2, N'$') AS phno
WHERE address.[key] = phno.[key];
输出
+------+---------+------+
| code | address | phno |
+------+---------+------+
| 123 | test1 | 123 |
| 123 | test2 | 456 |
| 123 | test3 | 789 |
+------+---------+------+
您可以为此使用递归 CTE:
with cte as (
select code, cast(NULL as varchar(max)) as address, cast(NULL as varchar(max)) as phno,
cast(address + ',' as varchar(max)) as rest_address, cast(phno + ',' as varchar(max)) as rest_phno, 0 as lev
from t
union all
select code, left(rest_address, charindex(',', rest_address) - 1), left(rest_phno, charindex(',', rest_phno) - 1),
stuff(rest_address, 1, charindex(',', rest_address), ''), stuff(rest_phno, 1, charindex(',', rest_phno), ''), lev + 1
from cte
where rest_address <> ''
)
select code, address, phno
from cte
where lev > 0;
Here 是一个 db<>fiddle.
如果列表中的元素可以超过 100 个,则需要 option (maxrecursion 0)
。