likes
comments
collection
share

mysql:这些函数你真的会用吗?

作者站长头像
站长
· 阅读数 9

不好意思,已经有一个多月没有更新了,这一个多月在外出差。在出差的过程中,与这边同事一起讨论一些业务,实现业务,发现原来MySql有很多函数自己并没有掌握,因此,干脆总结一番,当一个查询手册,以后用到可以直接进行查询。

废话不多说,开干!

准备工作:

我们随意创建一张表,添加数据:

create table user_info(
    id int auto_increment not null primary key comment '主键Id',
    user_name varchar(100) not null comment '用户名',
    age smallint not null comment '年龄',
     val varchar(30)
);


insert into user_info (user_name, age) values ('zhangsan',21,'1,2,3,4');
insert into user_info (user_name, age) values ('sili',25);
insert into user_info (user_name, age) values ('xili',32);
insert into user_info (user_name, age) values ('xiiili',26);
insert into user_info (user_name, age) values ('wangwu',31);
insert into user_info (user_name, age) values ('zhaoliu',22);

1、like

提到like,小伙伴们肯定会说这有啥难得,不就是模糊查询嘛,like 加单引号再加双百号,就能实现。

的确,like在我们日常工作中用的太多了,在熟悉不过了,但是我们还是要看下它的一些查询。

注:网上有很多说可以使用:[]查询区间内单个字符拼接查询,或者使用#单个数字的,其实mysql并不支持,like会将其整体作为一个字符串进行模糊查询。

1.1 _任意单个字符

需求: 查询以“ili”结尾的长度为4的用户名的数据

select * from user_info ui where ui.user_name like '_ili';

执行结果:

mysql:这些函数你真的会用吗?

从执行结果可以发现xiiili这个用户名称的用户并没有查询出来,符合需求。

1.2 %多字符模糊匹配

需求: 查询以“zhao”或“zhan”开头的用户名用户信息。

根据需求,我之前的写法直接是两个like进行查询:

select * from user_info ui where (ui.user_name like 'zhao%' or ui.user_name like 'zhan%');

2、regexp

说实话这个函数我基本没有用过,不过在搜寻mysql为啥不支持like中使用[]时发现的,因此记录一下。

regexp:支持正则表达式进行字段查询。

选项说明示例
^匹配文本的开始字符^6:表示查询以6开头的数据
$文本的结束字符6$:表示查询以6结尾的数据
.匹配任意单个字符'李.':表示以李开头的,长度为2的数据
*零个或多个字符'李*':表示以李开头的或是李数据
+前面的字符出现1次或多次'李四+':表示以李开头的,并包含四的数据
<字符串>包含字符串的数据即跟like '%%'一样的效果
[字符串]匹配字符集合任何一个字符[09]:即0和9任意一个数字。[0-9]:即0到9之间任意一个数字
[^]不匹配集合中任何一个字符即[]的非
字符串{n}字符串至少出现n次'g{2}':表示查询字段中至少包含2个或2个以上g的数据
字符串{n,m}前面的字符串至少出现n次,至多出现m次'g{2,4}':表示查询字段中至少包含2个g,至多包含4个g的数据

需求: 查询以“zhao”或“zhan”开头的用户名用户信息。

SELECT * FROM user_info WHERE user_name regexp '^zhao|^zhan';

执行结果:

mysql:这些函数你真的会用吗?

3、locate/find_in_set

locate与find_in_set都是查询字符或字符串在其他字符串中第一次出现的位置。

locate(n,m) :即n在m中第一次出现的位置,不包含时返回0。locate会将m作为一整个字符来进行匹配,不会因为存在逗号","而算成多个字符。

find_in_set(n,'m,n,l') :可以理解为n在一个集合中第一次出现的位置,多个字符匹配需要用逗号进行拼接且分隔的字符必须与n相等。

需求:查询用户名称中存在zhao的用户信息。

-- locate查询
select * from user_info ui where locate('zhao',ui.user_name) > 0;

--find_in_set查询
select * from user_info ui where find_in_set('zhao',ui.user_name) > 0;

执行结果:

  1. locate执行结果:

mysql:这些函数你真的会用吗?

  1. find_in_set查询:

mysql:这些函数你真的会用吗?

由查询结果我们可以看到locate实现了模糊匹配,而find_in_set查询是进行全匹配的,即与mysql中的=一样。

4、json_object

有时候我们希望一些字段以json的格式返回,此时可以使用json_object。

json_object:将查询的数据以json的格式输出。

json_object(key,value[,key,value......]) :key与value必填。

需求: 将用户名以"zhao"开头的用户信息,以json格式输出。

select json_object('userName',user_name,'age',age) jsonData from user_info ui where locate('zhao',ui.user_name) > 0;

执行结果:

mysql:这些函数你真的会用吗?

4.1 json操作

在很多数据库中一个字段可能会保存json格式的数据,我们也会对这些数据进行筛选等操作。那么我们来看下json数据怎么进行操作呢?

4.1.1 条件精确查找

格式:json字符 -> '$.字段名'=数值 json_contains(json数据,'查询值','查询json字段')

注:使用json_contains查询字符串匹配时,需加上""双引号,这是因为json数据中字符串是用双引号引用

例如,我们在上述生成的json中获取年龄为22的数据。

select *
from (
         select json_object('userName', user_name, 'age', age) jsonData
         from user_info ui
         where locate('zhao', ui.user_name) > 0) sel
where sel.jsonData -> '$.age' = 22;

-- 或

select *
from (
         select json_object('userName', user_name, 'age', age) jsonData
         from user_info ui
         where locate('zhao', ui.user_name) > 0) sel
where json_contains(sel.jsonData,'"zhaoliu"','$.userName');

执行结果:

mysql:这些函数你真的会用吗?

4.1.2 获取json属性值

我们可能会获取json中的某些数据的对应值展示到前端,这时候我们需要用到:json_extract

格式:json_extract(json数据,$.json字段名)

例如:我们在上述生成的json中获取字段年龄的数据。

select json_extract(sel.jsonData,'$.age') age
from (
         select json_object('userName', user_name, 'age', age) jsonData
         from user_info ui
         where locate('zhao', ui.user_name) > 0) sel

执行结果:

mysql:这些函数你真的会用吗?

4.1.3 条件模糊查找

对json数据模糊查询可以使用:json_extract获取字段值后结合like查询。

格式:json_extract(json数据,$.json字段名) like '%查询字符%' json字符 -> '$.字段名' like '%查询字符%'

例如:在上述生成的json数据中查询用户名包含zhao的数据。

select *
from (
         select json_object('userName', user_name, 'age', age) jsonData
         from user_info ui) sel
where json_extract(sel.jsonData,'$.userName') like '%zhao%';

-- 或
select *
from (
         select json_object('userName', user_name, 'age', age) jsonData
         from user_info ui) sel
where sel.jsonData -> '$.userName' like '%zhao%';

执行结果:

mysql:这些函数你真的会用吗?

当然mysql对于json的操作还提供了其他一些方法,有兴趣的小伙伴可以去官网看看,在此我就不一一介绍了。

5、substring_index

substring_index顾名思义就是通过索引来截取字符串。

应用:在字符串中可以根据某些字符的位置进行截取

substring_index('待截取字符串','截取字符','截取字符位置N')

当截取字符位置N为-1时表示截取从字符的最后出现的位置开始截取。相当于java中substring(str.lastIndexOf(",");

例如:定义一个字段:a,b,c,要截取第二个逗号前的字符

select SUBSTRING_INDEX('a,b,c', ',',2)

结果:

mysql:这些函数你真的会用吗?

5.1 行转列

在很多时候一列中数据可能会将多个值用逗号分隔而保存。也会因为业务要求要将逗号分隔的数据换成一列列数据进行统计。例如:一列数据为:1,2,3 需要转换成1为一行,2为1行,3为一行三行数据。

select substring_index(substring_index(uio.val, ',', xg.ID), ',', -1) vals
from user_info uio
         join xmjg_gmjjhylb xg on xg.ID <= (length(uio.val) - length(replace(uio.val, ',', '')) + 1)
where user_name = 'zhangsan';

执行结果:

mysql:这些函数你真的会用吗?

在行转列中用到了两个substring_index,其中:

substring_index(uio.val, ',', xg.ID) :会根据每一次循环的Id值不同,而获取到不同的字符。注:id必须要从1开始。

substring_index(substring_index(uio.val, ',', xg.ID), ',', -1) :根据获取的不同字符,获取逗号后面的一个值。

上述这些函数就是在我这一个多月出差中,会用到的,希望对大家有所启发。 期待小伙伴们也能够通过一些函数的用法,大家相互学习,共同进步。