大家好,我是知数堂SQL 优化班老师 网名:骑龟的兔子
在之前的的系列文章中,有意思的SQL(3) 行转列,列转行和复制
已经给大家介绍了,行转列,列转行,复制等方法。
在这篇文章中,对其进行更深一层的应用。
需求如下,
有一个表如下图所示
![e03c44d87d6638c9fcc7b4f44a0308ec.png](https://i-blog.csdnimg.cn/blog_migrate/033c848b7bd66cd80527638c3f7c6343.jpeg)
现在有个需求是,我在画面输入
'10004,22744,24007' 要求返回对应的三行数据
当然有很多种解决方案,一类是,在前端或者server端 用语言把输入值分开,
还有一种是在数据库端,本文介绍的是在数据库端的方法,
当然还有 最简单方案如下
![71e524db000b2fc9b9fabfeb591b1597.png](https://i-blog.csdnimg.cn/blog_migrate/e708416238b022e527a27a9e10fe2aa8.png)
这种方案,也可以解决输入值有空格的情况
![bcf1752e93489b4cb6d9ae59664a075d.png](https://i-blog.csdnimg.cn/blog_migrate/717db372818f7f25ea2eca8ee9f26ad5.png)
那这种方案的问题在哪呢?
先看下,这个表中是有索引的如下
![6d927b543d36f52bb6d66ddca34cd00e.png](https://i-blog.csdnimg.cn/blog_migrate/cc73907fcd83cc8df764d5a2bd173b1e.png)
运行了,下面的SQL 从执行计划中,可看出,走全表扫描了
![2bd38d30762ace555b051d74d07a7318.png](https://i-blog.csdnimg.cn/blog_migrate/9409dfde0f1e0b8119cfc338382be394.png)
也就是说表越大,有可能越慢!
写SQL 有几个阶段,第一个阶段是为了熟悉各种语法,和实现各种需求阶段
第二个阶段是,写出,更符合数据库特点,符合优化思路的SQL
上面的SQL 就是满足了需求,但是不符合优化。
如果写成如下
![fcde51207754e07d113f484fd21d4de2.png](https://i-blog.csdnimg.cn/blog_migrate/f8f85f99ae900a55942a0a953c90f132.png)
就可以有能满足需求,有能达到优化效果的SQL!
那现在的问题是,怎么把 '10004','22744','24007' 一行数据的变成3行数据的问题!
这样总算,文章又回到,本文开篇,没跑题~~
根据上篇文章,我们想把一行数据变成多行,我们需要复制
![ae5f79e23d928eb7a05828fa0bedbda8.png](https://i-blog.csdnimg.cn/blog_migrate/d18e3e58be302e9a771edfc526305b86.png)
这里我用到了MySQL 8.0 开始支持的with 语句,
不支持的可以用临时表代替。
其中 num 是为了复制而弄的中间表,可以理解为,我们中学的几何题中,为了解决问题画的辅助线~~。
上面的SQL 已经达到复制效果了,但是显然,复制的有点多了,我们只需要3行数据,但复制了5行,显然不行,我们观察下,结果发现我们如果复制的行数是逗号的个数+1 就可以了!
那怎么表达呢,我们用原来的length-去掉逗号后length +1 就可以
![631c5002159904f4165d30fd5d35cadd.png](https://i-blog.csdnimg.cn/blog_migrate/ef2f533c406a1fd384cdc402157335ac.png)
从上图所示,可以看出,这样就复制了我们想要的行数。
现在就剩下,怎么截取的问题,我们想要的是第一行截取第一个,第二行第二个,第n行第n个 。。。
MySQL 8.0给我们提供了regexp_substr这样的强大的函数,专门解决这样的问题
当然还有别的解决方案,为了代码的简单,我就用了这个函数
![9f839ebdfb49290cb75c5aa50cfd61db.png](https://i-blog.csdnimg.cn/blog_migrate/665f0e4e3defb1258be0f1fab9303f80.jpeg)
这样我们就解决了,行转列的问题,剩下的是把这部分带到原来的SQL 中,
执行计划如下,执行计划稍微有点复杂,初学者比较难懂
![9c472d94081d250d59ce3ce68cd99ac0.png](https://i-blog.csdnimg.cn/blog_migrate/727e60a594aa276f6dbc449d1bc72212.png)
下面是运行结果,还是符合需求的
![4cf12536bdfb217fd06b78eadebf265d.png](https://i-blog.csdnimg.cn/blog_migrate/b17f17713d9138dfdfffa73ae4bcc299.jpeg)
为了,给大家一个直观的感觉,我用大表salaries 表替换了原来的dept_emp表
然后运行SQL如下 运行了3.8 秒 !
![fef40cbf9ea8913c95a481050dc72d3d.png](https://i-blog.csdnimg.cn/blog_migrate/b200628bbc4012c59425d71e62c0c616.jpeg)
用修改之后代码 行数太多,我把数据删了保留时间如下 0.01秒
用倍数的话。。。
![7d7e198dffd223ee70e119eb2fc51a14.png](https://i-blog.csdnimg.cn/blog_migrate/11b20f167a4a27933850a659f49f6feb.jpeg)
本文,通过一个简单案例,给大家讲述了,SQL开发过程中的几个方法和优化思路,我们不仅仅开发过程中想到怎么解决需求,若果想进一步,就需要考虑性能问题
谢谢大家~
我是知数堂SQL 优化班老师~ ^^
如有关于SQL优化方面疑问和一起交流的请加 并且 @兔子@知数堂SQL优化
![3b39a90e6280eaba93133c360a1efa44.png](https://i-blog.csdnimg.cn/blog_migrate/f226015b75f6f4e18cfc9c83b417e83d.jpeg)