网站首页 > 教程文章 正文
一.前言
通常,在进行前端展示数据的需求中,我们都会遇到需要拆分字符串,或者将多行数据合并为一行的需求,当然,这两个需求可以看作是一对相反的操作。
则,一般情况下,在类似如下场景中,我们都是如下写相应的SQL脚本来实现的。
二.数据展示场景
假设,目前我们存在一张表t_goods,存储类似如下的数据:
select * from t_goods;
+------+------+---------------------+
| id | name | parts |
+------+------+---------------------+
| 1 | 衣服 | 尺码,颜色,品牌,产地 |
| 2 | 口红 | 色号,品牌 |
| 3 | 箱包 | 尺寸,重量,品牌 |
+------+------+---------------------+
现在,在web页面上需要展示全部的信息,但是展示数据的过程中,有个小问题,就是,当parts的数据太长的情况下,未显示全的数据部分需要用【...】来展示,如下图所示:
id | name | parts |
1 | 衣服 | 尺码,颜色... |
2 | 口红 | 色号,品牌 |
3 | 箱包 | 尺寸,重量... |
同时,当鼠标移动到【...】时,需要将所有的数据以列表的形式全部展示出来,如下图所示:
尺码 |
颜色 |
品牌 |
产地 |
三.拆分解决方案
一般情况下,我们都是借助一个有自增属性的列的表(例如表:t_id )和函数SUBSTRING_INDEX来解决此类问题。
select g.id
, g.name
, substring_index(substring_index(g.parts,',',t.n),',',-1) as part
from t_goods g join t_id t
on t.n <= length(g.parts)-length(replace(g.parts,',',''))+1
order by id;
返回的数据如下:
+------+------+------+
| id | name | part |
+------+------+------+
| 1 | 衣服 | 尺码 |
| 1 | 衣服 | 颜色 |
| 1 | 衣服 | 品牌 |
| 1 | 衣服 | 产地 |
| 2 | 口红 | 色号 |
| 2 | 口红 | 品牌 |
| 3 | 箱包 | 尺寸 |
| 3 | 箱包 | 重量 |
| 3 | 箱包 | 品牌 |
+------+------+------+
但是此种方法也是有比较明显的缺陷与不足的,如果自增列的值缺失,会造成数据返回的不完整。或许你会说,我专门定义一个表来存储,不允许任何人对表做修改,这样可以了吧?但是,如果是单独的服务器,这样是可以的。如果数据库服务器多了呢?分库分服务器也已经是常规操作。同时,另一个潜在的问题,就是,假设你需要维护的这个表中仅仅存储了最大值为100,但是,随着数据的变化,发现100已经无法满足需求,这时,便需要把所有的服务器上的这张表全部维护一遍。
那么是否有种一劳永逸的办法呢?或许MySQL的CTE真的是一个福音。下面就让我们来看看是如何解决的:
为了消除上面的隐含的几个小问题,我们借助递归CTE来试试:
with recursive my_cte as (
select 1 as n
, g.id
, g.name
, substring_index(substring_index(g.parts,',',1),',',-1) as part
from t_goods g
union all
select n+1
, g.id
, g.name
, substring_index(substring_index(g.parts,',',t.n+1),',',-1) as part
from t_goods g join my_cte t
on g.id = t.id and t.n < length(g.parts)-length(replace(g.parts,',',''))+1
)
select id
, name
, part
from my_cte
order by id;
对于递归CTE的用法和工作原理,请见我的另一篇文章:【MySQL之公共表表达式(CTE)】
对于其两者的性能,我这里未作对比,感兴趣的读者可以自行测试。
四.合并解决方案
最后,这里,稍微提下多行数据转换为一行,并用分隔符分割的解决方法,如下:
存在如下表t_goods_detail,其中存储的数据如下:
select * from t_goods_detail;
+------+------+------+
| id | name | part |
+------+------+------+
| 1 | 衣服 | 尺码 |
| 1 | 衣服 | 颜色 |
| 1 | 衣服 | 品牌 |
| 1 | 衣服 | 产地 |
| 2 | 口红 | 色号 |
| 2 | 口红 | 品牌 |
| 3 | 箱包 | 尺寸 |
| 3 | 箱包 | 重量 |
| 3 | 箱包 | 品牌 |
我们通常借助group_concat来解决,SQL如下:
select id
, name
, group_concat(part separator ',')
from t_goods_detail
group by id,name;
上述SQL脚本中,使用逗号(,)作为分隔符,大家也可以自定义分隔符为其它有效的特殊字符。
文末,本文如有不足,不妥之处,也恳请大家批评指出。
猜你喜欢
- 2024-12-18 MySQL备份表数据,备份表名加上当前时间
- 2024-12-18 在 Pandas 中使用 Merge、Join 、Concat合并数据的效率对比
- 2024-12-18 使用SQL语句将相同名的多行字段内容拼接起来
- 2024-12-18 如何避免出现 SQL 注入漏洞 如何有效防止sql注入
- 2024-12-18 MySQL递归查询上下级菜单 mysql如何递归查询
- 2024-12-18 做测试不会 SQL?超详细的 SQL 查询语法教程来啦
- 2024-12-18 mysql拼接函数讲解及配合截取函数使用
- 2024-12-18 Python语法之:Pandas数据合并总结
- 2024-12-18 比较常见类型漏洞讲解(三):SQL注入(一)
- 2024-12-18 SQL的基本函数 sql中的函数有哪些
- 最近发表
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- md5 sha1 (32)
- mybatis plus page (35)
- semaphore 使用详解 (32)
- update from 语句 (32)
- vue @scroll (38)
- 堆栈区别 (33)
- 在线子域名爆破 (32)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)