【发布时间】:2019-03-01 07:22:59
【问题描述】:
【问题讨论】:
-
这在任何 SQL 数据库中都是一件痛苦的事情。如果您可以在 SQL Server 之外处理此问题,那么我建议您这样做。
-
虽然,总的来说,我同意蒂姆的观点,但仍然添加了一些直接的方法来获得预期的解析结果
标签: sql sql-server excel database
【问题讨论】:
标签: sql sql-server excel database
很遗憾,SPLIT_STRING() 没有“序数”或“索引”选项。因此,您无法真正按已知顺序检索值。 (实际上,它确实会按顺序返回值,但不能保证。)
而且,SQL 表和结果集是无序的。因此,即使代码似乎可以工作,依赖排序也是一种非常糟糕的做法。
我建议使用递归 CTE:
with t as (
select 'prod1' as name, '3,5,6,9' as col1, '33,44,66,7' as col2, '66,7' as col3
),
cte as (
select name, 1 as lev,
convert(varchar(max), left(col1, charindex(',', col1 + ',') - 1)) as col1,
convert(varchar(max), stuff(col1, 1, charindex(',', col1 + ','), '')) as col1_rest,
convert(varchar(max), left(col2, charindex(',', col2 + ',') - 1)) as col2,
convert(varchar(max), stuff(col2, 1, charindex(',', col2 + ','), '')) as col2_rest,
convert(varchar(max), left(col3, charindex(',', col3 + ',') - 1)) as col3,
convert(varchar(max), stuff(col3, 1, charindex(',', col3 + ','), '')) as col3_rest
from t
union all
select name, lev + 1,
left(col1_rest, charindex(',', col1_rest + ',') - 1) as col1,
stuff(col1_rest, 1, charindex(',', col1_rest + ','), '') as col1_rest,
left(col2_rest, charindex(',', col2_rest + ',') - 1) as col2,
stuff(col2_rest, 1, charindex(',', col2_rest + ','), '') as col2_rest,
left(col3_rest, charindex(',', col3_rest + ',') - 1) as col3,
stuff(col3_rest, 1, charindex(',', col3_rest + ','), '') as col3_rest
from cte
where col1_rest <> '' or col2_rest <> '' or col3_rest <> ''
)
select name, col1, col2, col3
from cte;
Here 是一个 dbfiddle。
【讨论】:
一些免责声明:
STRING_SPLIT 需要 SQL Server 2016+MAXDOP 1 特意添加SQL:
-- seeding data
DECLARE @data TABLE ([Name] VARCHAR(50), Column1 VARCHAR(50), Column2 VARCHAR(50), Column3 VARCHAR(50))
INSERT @data VALUES ('Prod1', '3,5,6,9', '33,44,66,7', '66,7')
-- splitting strings into coluns
;WITH cte_col1 AS (
SELECT Name,
Col1.value AS ColumnValue,
ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS rn,
1 AS ColumnID
FROM @data d
CROSS APPLY STRING_SPLIT(d.Column1, ',') AS Col1
)
, cte_col2 AS (
SELECT Name,
Col2.value AS ColumnValue,
ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS rn,
2 AS ColumnID
FROM @data d
CROSS APPLY STRING_SPLIT(d.Column2, ',') AS Col2
)
, cte_col3 AS (
SELECT Name,
Col3.value AS ColumnValue,
ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS rn,
3 AS ColumnID
FROM @data d
CROSS APPLY STRING_SPLIT(d.Column3, ',') AS Col3
)
-- gluing all parts together
SELECT
d.Name
, min (CASE WHEN d.ColumnID = 1 THEN d.ColumnValue END ) AS Column1
, min (CASE WHEN d.ColumnID = 2 THEN d.ColumnValue END ) AS Column2
, min (CASE WHEN d.ColumnID = 3 THEN d.ColumnValue END ) AS Column3
FROM (
SELECT Name, ColumnValue, rn, cte_col1.ColumnID FROM cte_col1
UNION ALL
SELECT Name, ColumnValue, rn, cte_col2.ColumnID FROM cte_col2
UNION ALL
SELECT Name, ColumnValue, rn, cte_col3.ColumnID FROM cte_col3
) d
GROUP BY d.Name, d.rn
ORDER BY d.Name, d.rn
OPTION (MAXDOP 1)
结果成:
Name Column1 Column2 Column3
Prod1 3 33 66
Prod1 5 44 7
Prod1 6 66 NULL
Prod1 9 7 NULL
【讨论】: