在 MySQL 中实现多个字符拆分并并行转列操作,可借助序号表和字符串处理函数。
### 原理
利用 `SUBSTRING_INDEX` 函数按指定分隔符拆分字符串,结合序号表生成连续序号,通过交叉连接(`CROSS JOIN`)将序号与拆分后的字符串元素关联,实现行转列。
### 示例代码
#### 场景一:拆分 `user` 表中 `mobile` 字段
假设 `user` 表存储用户信息,`mobile` 字段以逗号分隔存储多个手机号码。使用以下 SQL 语句拆分并转列:
```sql
SELECT
NAME,
REPLACE(
SUBSTRING_INDEX(mobile, ',', a.id),
CONCAT(
SUBSTRING_INDEX(mobile, ',', a.id - 1),
','
),
''
) AS mobile
FROM
squence a
CROSS JOIN (
SELECT
NAME,
CONCAT(mobile, ',') AS mobile,
LENGTH(mobile) - LENGTH(REPLACE(mobile, ',', '')) + 1 AS size
FROM
`user`
) b
ON a.id <= b.size;
```
此 SQL 借助 `squence` 表生成连续 `id`,通过交叉连接将 `id` 与 `user` 表中 `mobile` 字段拆分后的元素关联,最终实现 `mobile` 字段拆分并转列 [^2]。
#### 场景二:拆分 `rfsr` 表中 `FAIL_REASON` 字段
假设 `rfsr` 表存储金融服务结果信息,`FAIL_REASON` 字段以逗号或竖线分隔存储多个失败原因。使用以下 SQL 语句拆分并转列:
```sql
SELECT
ids,
id,
APPLY_ID,
REPLACE(
SUBSTRING_INDEX(REASON, ',', a.ids),
CONCAT(
SUBSTRING_INDEX(REASON, ',', a.ids - 1),
','
),
''
) AS REASON
FROM
t_squence a
CROSS JOIN (
SELECT
id,
APPLY_ID,
CONCAT(REASON, ',') AS REASON,
LENGTH(REASON) - LENGTH(REPLACE(REASON, ',', '')) + 1 AS size
FROM (
SELECT
id,
APPLY_ID,
left(substring(REPLACE(REASON,',,',','),2),length(substring(REPLACE(REASON,',,',','),2))-1) REASON
FROM (
SELECT
id,
APPLY_ID,
CERT_NO,
REPLACE(GROUP_CONCAT(FAIL_REASON),'|',',') AS REASON
FROM
rcs_finance_ser_result rfsr
WHERE
rfsr.final_result='AD'
AND rfsr.cert_no='411201199110164491'
GROUP BY
rfsr.CERT_NO
) t
) tt
) b
ON a.ids <= b.size;
```
此 SQL 先对 `FAIL_REASON` 字段进行预处理,将竖线替换为逗号,去除多余逗号,再借助 `t_squence` 表生成连续 `ids`,通过交叉连接将 `ids` 与 `FAIL_REASON` 字段拆分后的元素关联,最终实现 `FAIL_REASON` 字段拆分并转列 [^3]。
### 代码解释
- `SUBSTRING_INDEX(str,delim,count)`:按指定分隔符 `delim` 拆分字符串 `str`,`count` 为正返回定界符左边内容,为负返回右边内容 [^1]。
- `REPLACE(str,from_str,to_str)`:将字符串 `str` 中 `from_str` 替换为 `to_str`。
- `LENGTH(str)`:返回字符串 `str` 的长度。
- `GROUP_CONCAT(expr)`:将分组后的数据连接成一个字符串。
- `CROSS JOIN`:实现两个表的交叉连接,生成笛卡尔积。
### 注意事项
- 需创建序号表(如 `squence` 或 `t_squence`),其 `id` 或 `ids` 范围应根据实际拆分后元素数量确定。
- 若字符串包含多种分隔符,需先统一分隔符,再进行拆分操作。