SQL Server中按条件将单列拆分为多列的实现方法(附实例)
在SQL Server中将单列按连字符拆分为固定多列
针对你的emp表需求,这里提供两种实用的实现方式,适配不同版本的SQL Server:
方法一:使用STRING_SPLIT + PIVOT(SQL Server 2016及以上版本)
这种方法更简洁高效,利用内置字符串拆分函数配合数据透视完成行转列:
WITH split_data AS ( SELECT id, name_part, 'prod' + CAST(ROW_NUMBER() OVER(PARTITION BY id ORDER BY (SELECT NULL)) AS VARCHAR(10)) AS prod_col FROM emp CROSS APPLY STRING_SPLIT(name, '-') AS parts(name_part) ) SELECT id, ISNULL(prod1, '') AS prod1, ISNULL(prod2, '') AS prod2, ISNULL(prod3, '') AS prod3, ISNULL(prod4, '') AS prod4, ISNULL(prod5, '') AS prod5 FROM split_data PIVOT ( MAX(name_part) FOR prod_col IN (prod1, prod2, prod3, prod4, prod5) ) AS pivot_result ORDER BY id;
代码说明:
STRING_SPLIT(name, '-'):把name列按连字符拆分成多行,每个拆分片段作为name_part。ROW_NUMBER() OVER(PARTITION BY id ORDER BY (SELECT NULL)):为每个id下的拆分片段按顺序编号,生成prod1、prod2这类列名标识。PIVOT:将行数据转换为列,把编号对应的片段填入对应prod列。ISNULL(...):确保没有对应拆分片段的列显示为空字符串而非NULL。
方法二:使用SUBSTRING + CHARINDEX(兼容低版本SQL Server)
如果你的SQL Server版本低于2016(无STRING_SPLIT函数),可以用字符串截取的方式实现:
SELECT id, -- 提取prod1:第一个连字符前的内容 LEFT(name, CHARINDEX('-', name + '-') - 1) AS prod1, -- 提取prod2:第一个与第二个连字符之间的内容 SUBSTRING( name, CHARINDEX('-', name) + 1, CHARINDEX('-', name + '-', CHARINDEX('-', name) + 1) - CHARINDEX('-', name) - 1 ) AS prod2, -- 提取prod3:第二个与第三个连字符之间的内容 SUBSTRING( name, CHARINDEX('-', name + '-', CHARINDEX('-', name) + 1) + 1, CHARINDEX('-', name + '-', CHARINDEX('-', name + '-', CHARINDEX('-', name) + 1) + 1) - CHARINDEX('-', name + '-', CHARINDEX('-', name) + 1) - 1 ) AS prod3, -- 提取prod4:第三个与第四个连字符之间的内容 SUBSTRING( name, CHARINDEX('-', name + '-', CHARINDEX('-', name + '-', CHARINDEX('-', name) + 1) + 1) + 1, CHARINDEX('-', name + '-', CHARINDEX('-', name + '-', CHARINDEX('-', name + '-', CHARINDEX('-', name) + 1) + 1) + 1) - CHARINDEX('-', name + '-', CHARINDEX('-', name + '-', CHARINDEX('-', name) + 1) + 1) - 1 ) AS prod4, -- 提取prod5:第四个连字符后的内容 REVERSE(LEFT(REVERSE(name), CHARINDEX('-', REVERSE(name) + '-') - 1)) AS prod5 FROM emp ORDER BY id;
代码说明:
- 用
CHARINDEX定位连字符的位置,结合LEFT和SUBSTRING截取对应片段。 - 在
name后拼接-是为了处理拆分片段不足的情况,避免函数报错。 - 最后用
REVERSE简化最后一个片段的提取逻辑。
执行任意一种方法,都能得到你期望的输出:
| id | prod1 | prod2 | prod3 | prod4 | prod5 |
|---|---|---|---|---|---|
| 1 | lux | pen | oxo | mobile | |
| 2 | pne | soap | |||
| 3 | hop | pen | mobile | soap | jad |
| 4 | pen | soap | box |
内容的提问来源于stack exchange,提问作者harni




