如何使用SQL实现记录的Unflatten(反扁平化)?
如何用SQL实现数据反扁平化(拆分逗号分隔值为多行)
可以实现,不同数据库有对应的SQL语法处理这类将逗号分隔字符串拆分为多行的需求,以下是几种主流数据库的实现方案:
MySQL(8.0及以上版本)
方案1:递归CTE
WITH RECURSIVE split_data AS ( SELECT IDV, `VALUES` AS original_val, SUBSTRING_INDEX(`VALUES`, ',', 1) AS split_val, SUBSTRING(`VALUES`, LENGTH(SUBSTRING_INDEX(`VALUES`, ',', 1)) + 2) AS remaining_val FROM your_table WHERE `VALUES` IS NOT NULL AND `VALUES` != '' UNION ALL SELECT IDV, original_val, SUBSTRING_INDEX(remaining_val, ',', 1) AS split_val, SUBSTRING(remaining_val, LENGTH(SUBSTRING_INDEX(remaining_val, ',', 1)) + 2) AS remaining_val FROM split_data WHERE remaining_val IS NOT NULL AND remaining_val != '' ) SELECT IDV, split_val AS `VALUES` FROM split_data;
方案2:JSON_TABLE(更简洁)
SELECT t.IDV, j.split_val AS `VALUES` FROM your_table t JOIN JSON_TABLE( CONCAT('["', REPLACE(t.`VALUES`, ',', '","'), '"]'), '$[*]' COLUMNS (split_val VARCHAR(255) PATH '$') ) j;
PostgreSQL
利用string_to_array将字符串转为数组,再用unnest展开数组为多行:
SELECT IDV, unnest(string_to_array("VALUES", ',')) AS "VALUES" FROM your_table;
SQL Server(2016及以上版本)
使用内置的STRING_SPLIT函数配合CROSS APPLY:
SELECT t.IDV, s.value AS [VALUES] FROM your_table t CROSS APPLY STRING_SPLIT(t.[VALUES], ',') s;
Oracle(11g及以上版本)
通过REGEXP_SUBSTR结合CONNECT BY递归拆分:
SELECT IDV, REGEXP_SUBSTR("VALUES", '[^,]+', 1, LEVEL) AS "VALUES" FROM your_table CONNECT BY LEVEL <= REGEXP_COUNT("VALUES", ',') + 1 AND PRIOR IDV = IDV AND PRIOR SYS_GUID() IS NOT NULL;
注意事项
- 替换代码中的
your_table为实际表名; - 若
VALUES是数据库关键字,需用对应数据库的标识符包裹(如MySQL用反引号、SQL Server用方括号、PostgreSQL/Oracle用双引号),避免语法错误。
内容的提问来源于stack exchange,提问作者rholdberh
相关产品推荐
相关产品推荐

