如何通过SQL将单行单列的逗号分隔字符串转换为多列?
如何通过SQL将单行单列的逗号分隔字符串转换为多列?
嘿,这个需求我之前也碰到过!本质上是先把逗号分隔的字符串拆成单独元素,再把这些元素转成列名,最后给每个列填充固定值(这里是1)。下面我分不同数据库讲具体实现方法,你可以对着自己用的数据库来选:
一、如果元素数量固定(比如你例子里的4个)
这种情况最简单,直接写死列名就行,不用复杂的动态SQL:
MySQL / MariaDB
SELECT 1 AS `Column A`, 1 AS `Column B`, 1 AS `Column C`, 1 AS `Column D` FROM your_table;
SQL Server
SELECT 1 AS [Column A], 1 AS [Column B], 1 AS [Column C], 1 AS [Column D] FROM your_table;
PostgreSQL
SELECT 1 AS "Column A", 1 AS "Column B", 1 AS "Column C", 1 AS "Column D" FROM your_table;
二、如果元素数量不固定(需要动态生成列)
如果字符串里的元素个数可能变化,就得用动态SQL自动生成列,下面是各数据库的实现:
SQL Server
先拆分字符串,再用动态PIVOT转成列:
DECLARE @cols NVARCHAR(MAX), @query NVARCHAR(MAX); -- 生成列名列表(比如[Column A],[Column B]...) SELECT @cols = STRING_AGG(QUOTENAME('Column ' + TRIM(value)), ',') FROM your_table CROSS APPLY STRING_SPLIT(column1, ','); -- 构造动态查询语句 SET @query = ' SELECT ' + @cols + ' FROM ( SELECT 1 AS val, ''Column '' + TRIM(value) AS col_name FROM your_table CROSS APPLY STRING_SPLIT(column1, '','') ) src PIVOT ( MAX(val) FOR col_name IN (' + @cols + ') ) pvt'; -- 执行动态SQL EXEC sp_executesql @query;
MySQL 8.0+
用JSON_TABLE拆分字符串,再结合动态SQL:
-- 先获取所有列名 SET @cols = ( SELECT GROUP_CONCAT(DISTINCT CONCAT('1 AS `Column ', TRIM(val), '`')) FROM your_table, JSON_TABLE( CONCAT('["', REPLACE(column1, ',', '","'), '"]'), '$[*]' COLUMNS(val VARCHAR(255) PATH '$') ) AS jt ); -- 构造并执行动态查询 SET @query = CONCAT('SELECT ', @cols, ' FROM your_table'); PREPARE stmt FROM @query; EXECUTE stmt; DEALLOCATE PREPARE stmt;
PostgreSQL
用string_to_array+unnest拆分,再结合动态SQL和crosstab:
-- 先安装tablefunc扩展(如果没装过) CREATE EXTENSION IF NOT EXISTS tablefunc; -- 获取列名列表 WITH split_cols AS ( SELECT DISTINCT 'Column ' || TRIM(unnest(string_to_array(column1, ','))) AS col_name FROM your_table ) SELECT string_agg(quote_ident(col_name) || ' int', ',') INTO @cols FROM split_cols; -- 获取列名用于crosstab的第二个参数 SELECT string_agg(quote_literal(col_name), ',' ) INTO @col_list FROM split_cols; -- 构造动态查询 SET @query = CONCAT( 'SELECT * FROM crosstab(', '''SELECT 1 AS row_id, ''Column '' || TRIM(unnest(string_to_array(column1, '',''))) AS col_name, 1 AS val FROM your_table'',', '''SELECT unnest(array[', @col_list, '])''', ') AS ct(row_id int, ', @cols, ')' ); -- 执行动态SQL EXECUTE @query;
小提示
- 注意字符串里的空格:我在所有例子里都加了
TRIM()来去掉元素前后的空格(比如你的例子里的"A, B,C, D"有空格),如果你的字符串没有空格,可以去掉TRIM()。 - 动态SQL要注意SQL注入风险,如果你的字符串内容是用户输入的,要额外做校验哦!
备注:内容来源于stack exchange,提问作者P3P0
相关产品推荐
相关产品推荐

