惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 三生石上(FineUI控件)
V
Vulnerabilities – Threatpost
C
Cisco Blogs
A
Arctic Wolf
L
LINUX DO - 热门话题
P
Proofpoint News Feed
Security Latest
Security Latest
AWS News Blog
AWS News Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
L
Lohrmann on Cybersecurity
W
WeLiveSecurity
爱范儿
爱范儿
Last Week in AI
Last Week in AI
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
Security Affairs
PCI Perspectives
PCI Perspectives
C
Cybersecurity and Infrastructure Security Agency CISA
Spread Privacy
Spread Privacy
IT之家
IT之家
月光博客
月光博客
云风的 BLOG
云风的 BLOG
宝玉的分享
宝玉的分享
J
Java Code Geeks
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
I
Intezer
博客园_首页
博客园 - 司徒正美
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Palo Alto Networks Blog
NISL@THU
NISL@THU
Recent Commits to openclaw:main
Recent Commits to openclaw:main
有赞技术团队
有赞技术团队
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
量子位
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
N
News and Events Feed by Topic
Webroot Blog
Webroot Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Security @ Cisco Blogs
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
The Cloudflare Blog
V
V2EX
Jina AI
Jina AI

博客园 - 大汪的数据之路

星环大数据使用体验 vibe coding使用体验 基于SQL实现分组的文字排序聚合 数据码农马年大吉 BI报表及可视化分析类工具使用经验总结(下) BI报表及可视化分析类工具使用经验总结(上) 基于Python实现自动化微信通知和预警 Chat2DB测试体验 常用数据管理工具与平台汇总 OneID系统建设实践总结 网易有数BI使用总结 网易NDH大数据平台使用经验 版本管理总结 程序自动化vs人工手动处理 SQL开发总结 数据平台使用经验 数据团队运维值班任务简介 Python环境安装、管理与部署 windows获取kerberos认证 SQL动态长度行列转置 ODI Scenario 场景 Oracle KEEP 分析函数
字符串分割并展开成表格的SQL实现方法
大汪的数据之路 · 2026-01-20 · via 博客园 - 大汪的数据之路

一、场景案例

在数据开发类项目中,常常会遇到需要将字符串进行切割并展开成表格的场景,如以下两种常见的案例:

  1. 标签类型数据:如将员工标签类型的数据
    - 技能:Java、Spring、微服务、项目管理
    - 项目经验:电商、金融、教育
    - 工作风格:#执行力强 #跨部门协作 #数据驱动
  2. 分类层级数据:如将组织部门层级数据:“/集团/分公司/信息技术部/数据团队”

除此之外,在一些特定的业务场景中,如证券场景中,需要将一笔回购合约涉及到的多个质押券进行拆分(提取每个质押券有质押数量及对应标准券转换比例),数据示例如下:

image

 另外,API请求的返回的数据多为半结构化的字典列表数据,需要将每行数据从列表中进行提取出来再进行后续的处理,如以下数据:

{"data": [
   {
"AMOUNT":-9000,"SUB_TYPE_NAME":"债券分销","BRANCH_NAME":"银行间","TYPE_NAME":"收入","BUSI_DATE":"20250831","PROJECT_NAME":"调整1月分销佣金-24****MTN001"}, {"AMOUNT":-1075.61,"SUB_TYPE_NAME":"债券分销","BRANCH_NAME":"银行间","TYPE_NAME":"收入","BUSI_DATE":"20250531","PROJECT_NAME":"调整计提1月及3月分销佣金"} ], "success":true }

二,各类主流SQL方言实现方法

针对这类场景,目前没有标准SQL函数支持实现该功能。各类SQL方言通过自定义方法进行支持,以下是常用的实现方法。

Spark/Hive SQL

采用split + explode(及升级版posexplode)。以下为测试案例:

0

 利用该方法可以轻松的回购质押券进行拆分处理:

image

PostgreSQL

有两种方法:

方法一:首先利用string_to_array将字符串切割成数组,然后利用unnest将数组扩展成表

image

方法二:直接利用regexp_split_to_table将字符串切割并转换成表

image

select string_to_array('apple,banana,orange', ',') as item;
select string_to_array('apple|banana|orange', '|') as item;
select unnest(string_to_array('apple,banana,orange', ',')) as item;

select regexp_split_to_array('apple|banana|orange', '\|') as item;
select regexp_split_to_table('apple|banana|orange', '\|') as item;

View Code

Oracle

利用connect by + Level来实现

0

WITH CTE_DATA AS (
    SELECT 'tom' AS NAME, 'apple,banana,cherry' AS FRUIT FROM DUAL
)
SELECT NAME, REGEXP_SUBSTR(FRUIT, '[^,]+', 1, LEVEL) AS FRUIT
FROM CTE_DATA
CONNECT BY REGEXP_SUBSTR(FRUIT, '[^,]+', 1, LEVEL) IS NOT NULL
;

View Code

MySQL

5.x+版本只能使用数字辅助表+SUBSTRING_INDEX。

image

CREATE TABLE IF NOT EXISTS numbers (n INT PRIMARY KEY);
INSERT INTO numbers
SELECT a.N + b.N * 10 + c.N * 100 + 1 AS n
FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) a
CROSS JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) b
CROSS JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) c;
-- 使用数字表分割
SELECT
SUBSTRING_INDEX(
SUBSTRING_INDEX('a,b,c,d', ',', numbers.n),
',',
-1
) AS part
FROM numbers
WHERE numbers.n <= LENGTH('a,b,c,d') - LENGTH(REPLACE('a,b,c,d', ',', '')) + 1;

View Code

8.0+版本可使用json_table

SELECT 
    o.order_id,
    j.product_id
FROM orders o
JOIN JSON_TABLE(
    CONCAT('["', REPLACE(o.product_ids, ',', '","'), '"]'),
    '$[*]' COLUMNS (product_id INT PATH '$')
) AS j;

SQL Server

早期版本无内置函数,只能通过自定义表值函数(TVF)或者XML方法

CREATE FUNCTION dbo.SplitString
(
    @String NVARCHAR(MAX),
    @Delimiter CHAR(1)
)
RETURNS @Results TABLE 
(
    ID INT IDENTITY(1,1),
    Value NVARCHAR(MAX)
)
AS
BEGIN
    DECLARE @pos INT = 0
    DECLARE @slice NVARCHAR(MAX)

    IF RIGHT(@String, 1) != @Delimiter
        SET @String = @String + @Delimiter

    WHILE CHARINDEX(@Delimiter, @String) > 0
    BEGIN
        SET @pos = CHARINDEX(@Delimiter, @String)
        SET @slice = LEFT(@String, @pos - 1)
        
        INSERT INTO @Results (Value) VALUES (@slice)
        SET @String = STUFF(@String, 1, @pos, '')
    END
    
    RETURN
END

-- 使用示例
SELECT * FROM dbo.SplitString('张三,李四,王五', ',')

View Code

DECLARE @str NVARCHAR(100) = '苹果|香蕉|橙子';
DECLARE @separator CHAR(1) = '|';

SELECT 
    LTRIM(RTRIM(m.n.value('.[1]', 'NVARCHAR(100)'))) AS SplitValue
FROM 
    (SELECT CAST('<x>' + REPLACE(@str, @separator, '</x><x>') + '</x>' AS XML)) AS t(x)
CROSS APPLY 
    x.nodes('/x') AS m(n);

View Code

2016之后的版本可使用原生方法STRING_SPLIT

--带序号的版本(SQL Server 2022+)
SELECT value, ordinal
FROM STRING_SPLIT('a,b,c', ',', 1) -- 第三个参数启用序号

三、结论

  Spark SQL、PostgreSQL最方便,思路也比较相似,都是先将字符串拆分数组,然后扩展成表。SQLServer新版本实现较为方法,直接一个函数搞定。Oracle利用其connect by来实现,也相对便捷,只是相对主流SQL方言比较小众一点。Mysql新版本相对方便一点,老版本需要辅助表增加维护成本。

四、参考链接