前言

作为后端开发的我们,在日常工作中,经常会接到客户、运营或者产品经理提的一些临时需求。

比如:给你一个订单号,查询有哪些商品有问题,或者提供提出这样一个需求,按某种格式导出某些表某些字段的数据。

为了快速解决线上问题,或者满足他们提出的这些临时需求,我们经常需要写一些SQL脚本,来实现这些需求。

当然临时需求太多了,我没办法一一列举,这篇文章的重点是更大家一起聊聊:

  1. 如何将多行数据转换成一行。
  2. 如何将一行数据转换成多行。

这两个需求是日常工作中经常会遇到,希望这篇文章对你会有所帮助。

1 将多行转换成一行

假如现在有一张用户表,有这些数据:image产品有一个需求,想要找出年龄等于23岁的用户id,拼接成一个字符串给他。

过滤产品想要的数据非常容易,用下面这条sql就能轻松实现:

select id from user where age=23;

但该SQL的执行结果是下面这样的:image获取到的用户id,返回了多行数据。

怎么才能变成一行数据呢?

答:这就可以使用MySQL自带的group_concat()函数了。

将SQL语句改造这样的:

select group_concat(id) from user where age=23;

执行结果:image只返回了一条数据,多个用户id用逗号分割,拼接成了一个字符串。

这样就可以实现多行转一行了。

2 将一行转换成多行

有时候,我们需要将一行转成多行。

假如有这样一种场景。

有一张产品表,里面的数据是这样的:

image

还有一张订单表,里面的数据是这样的:image

其中订单表中有个字段product_id,其实是一个varchar类型,保存的是多个产品id用逗号拼接而成的数据。

现在客户有这样一个需求,要导出表中的订单和商品信息,返回的字段有:订单id,订单code,订单name,商品id,商品name和商品model。

这个需求乍一看,很简单。

只需要将订单表和商品表,这两张表join,起来不就完成任务了?

确实要怎么做,但是两张表join时,跟在on关键字后面的条件是什么呢?

用等于号吗?

select s1.id,s1.code,s1.name,s2.id,s2.name,s2.model
from`order`s1
inner join product s2
on s1.product_id=s2.id

显然不对,只返回了测试商品1的数据,其他的商品都没有返回。image

用in关键字?

select s1.id,s1.code,s1.name,s2.id,s2.name,s2.model
from `order`s1
inner join products2
on s2.id in (s1.product_id)

也不对。image跟刚刚的返回结果是一样的。

s2.id是数字类型的,而s1.product_id是字符串类型的,会不会是二者类型不一致,导致查出的数据问题?

使用concat函数将s2.id转换成了字符串类型:

select s1.id,s1.code,s1.name,s2.id,s2.name,s2.model
from `order`s1
inner join product s2
on concat(s2.id,'') in (s1.product_id)

执行结果就更不对了,连数据都没返回。image使用split函数分割s1.product_id字段中的字符串,变成多个值?

很不幸的是在MySQL5.7是不支持split这个函数的。

有没有其他的解决办法呢?

答:使用find_in_set()函数。

将上面的sql调整一下:

select s1.id,s1.code,s1.name,s2.id,s2.name,s2.model
from `order`s1
inner join product s2
on (find_in_set(s2.id,s1.product_id)<>0)

执行结果:image执行了客户的需求,将一行数据转换成了多行数据。

最后修改:2026 年 06 月 06 日
如果觉得我的文章对你有用,请随意赞赏