当前业务需求:
根据某一个字段的字符串通过指定的分隔符,将原始的一行数据分隔为多行数据
原数据:
需要的结果数据格式
实现sql:
select acct.id, substring_index(substring_index(many, ',', h.id), ',', -1) as one
from sys acct
cross join help_select_id h
where h.id < (char_length(many) - char_length(replace(many, ',', '')) + 2)
分析 :
select acct.id,
# 由于数据保存使用的是逗号分隔;所以进行取元素
substring_index(
substring_index(many, ',', h.id)
, ',', -1) as one
from sys acct
# 创建的一个辅助表;此表只有一个id字段;数据值是自增;由于数据是我自己插入的;所以第一条数
# 据是从1开始的;假如此表的第一条数据id是0;那么需要修改where条件后面 +的数量为1而不是2
# 注意 ①help_select_id 表的数据需要是自增的;每个id之间的间隔是1;不可存在 2,4这种跳跃式数据;
#② 此表的id的个数必须大于等于 many字段的分隔符最多的个数[例如:如果 many = 'AD,SS,SE,WW'是该字段
# 以逗号为分隔符,逗号最多的值;那么 help_select_id的id个数必须大于等于 3]
cross join help_select_id h
where h.id
# 首先计算出逗号的个数;此处后面 +2 的原因
# ①如果直接使用 h.id < char_length(many) - char_length(replace(many, ',', '')) 会造成数据的缺失;
# 原因分析: 假如 many = 'AD,WJ,KS,' ;上面计算出的差值是3,即实际判断条件为 h.id < 3 ;
# 由于我的 help_select_id表的第一条数据是从1开始的;那么满足这个条件的就有两条;
# 然后整个执行的sql可以理解为下面的语句
# select acct.id,
# 得到最终字符串 AD
# substring_index(
# 得到字符串 AD
# substring_index('AD,WJ,KS,' ,',' ,1)
# , ',' ,-1) as one
# from sys acct cross join help_select_id h where h.id = 1 union
# select acct.id,
# 得到最终字符串 WJ
# substring_index(
# 得到字符串 AD,WJ
# substring_index('AD,WJ,KS,' ,',' ,2)
# , ',' ,-1) as one
# from sys acct cross join help_select_id h where h.id = 2;
# 上面的sql执行的结果只会是两条 id one
# 1 AD
# 1 WJ
# 就会造成KS数据的缺失;
# 那加1就好了;为什么要加2呢? 如果你的字段数据后缀都以逗号结尾,确实+1以满足需求;但如果你的字段数据不是
# 以逗号结束,那么就又少了一条
# ②例如 many='AD,WJ,KS' ;注意此值和①中的值相比,结尾少了一个逗号;那么
# h.id < char_length(many) - char_length(replace(many, ',', '')) + 1 只加1 结果相当于 h.id < 3
# 由于我的 help_select_id表的第一条数据是从1开始的;那么满足这个条件的就有两条;
# 然后整个执行的sql可以理解为下面的语句
# select acct.id,
# 得到最终字符串 AD
# substring_index(
# 得到字符串 AD
# substring_index('AD,WJ,KS' ,',' ,1)
# , ',' ,-1) as one
# from sys acct cross join help_select_id h where h.id = 1 union
# select acct.id,
# 得到最终字符串 WJ
# substring_index(
# 得到字符串 AD,WJ
# substring_index('AD,WJ,KS' ,',' ,2)
# , ',' ,-1) as one
# from sys acct cross join help_select_id h where h.id = 2;
# 上面的sql执行的结果只会是两条 id one
# 1 AD
# 1 WJ
# 所以 需要 +2 ;注意:我的 help_select_id表的数据是从1开始的;如果你是从0开始,那就应该只 +1 即可
< (char_length(many) - char_length(replace(many, ',', '')) + 2)