mysql的函数使用及其他小技巧

目录

mysql的系统方面

1> mysql的登录命令:

2>创建,删除,使用数据库:

mysql函数

关于对字段的分割find_in_set('参数',字段名);

convert函数及扩展cast函数

left函数及扩展right函数和SUBSTRING、SUBSTRING_index

HEX函数

CONV函数

INTERVAL函数

elt函数


我这篇为mysql的一些命令的杂记

注:本博客的sql我都有本地执行,但可能会因为博客的空格/换行符导致sql报错,如果有报错可以手打一遍或者在编辑器上重新复制下,我有遇到过sql 粘贴上来  再copy实用报错 

mysql的系统方面

1> mysql的登录命令:

    下面是几种登陆到MySql数据库的登陆方式代码(我最喜欢2),刚刚安装mysql的root账户是没有密码的.

     1.mysql -u root -ppassword

     2.mysql -u root -p
       Enter password:password
     3.mysql -h localhost -u root -ppassword
     4.mysql -h 127.0.0.1 -u root -ppassword

2>创建,删除,使用数据库:

   create database  '数据库名';

   use  '数据库名';

   drop database '数据库名';

 

mysql函数

关于对字段的分割find_in_set('参数',字段名);

今天有一个业务场景需要一个字段进行一个查询,而改字段存放的是标签, 格式为:101,102,103

所以在查询的时候需要将该字段进行切割,当然也可以在查询的时候在该字段的内容前后分别加上,号来进行like 查询.

不过呢我想用切割的来,mysql作为一个成熟的数据库果然还是有支持的机制的,字段值用英文逗号分隔,

比如‘未分组,VIP会员,广东客'查询时

select * from `table_a` where id=20 and find_in_set('未分组', group_name);

或者

select * from `table_a` where id=20 and find_in_set('未分组', group_name)>0;

这两种都可以 但是在hibernate框架中只能用第二种,不然会抛异常

因为是原生支持的做法,mysql会对其进行优化.

 

最近在做一个根据省份的首字母进行排序的需求, 其中有许多接触的点感觉可以记一下.

在网上找资料的结果

 select  *
 FROM 表名
 order by  ELT(
 INTERVAL(
 CONV(
 HEX(left(CONVERT(字段名 USING gbk),1)),
 16,10),     
0xB0A1,0xB0C5,0xB2C1,0xB4EE,0xB6EA,0xB7A2,0xB8C1,0xB9FE,0xBBF7,     
0xBFA6,0xC0AC,0xC2E8,0xC4C3,0xC5B6,0xC5BE,0xC6DA,0xC8BB,0xC8F6,
0xCBFA,0xCDDA,0xCEF4,0xD1B9,0xD4D1),     
'A','B','C','D','E','F','G','H','J','K','L','M','N','O','P','Q','R','S','T','W','X','Y','Z') asc

如上,一共用来6个函数: 

one by one

convert函数及扩展cast函数

convert函数有两种 :  

  1. convert(参数,类型) 功能等同于 cast(参数 as 类型) 将参数转换为指定类型
  2. convert(参数 using 字符集)  将参数转换为指定字符集
  3. cast(参数 AS 类型) convert(参数,类型)  
    可以转换的类型是有限制的。这个类型可以是以下值其中的一个:
    二进制,同带binary前缀的效果 : BINARY    
      字符型,可带参数 : CHAR()     
      日期 : DATE     
      时间: TIME     
      日期时间型 : DATETIME     
      浮点数 : DECIMAL      
      整数 : SIGNED     
      无符号整数 : UNSIGNED

例:

select convert('123.26' ,DECIMAL(20,2)); -- 结果:123.26

 

select cast('123.26' AS DECIMAL(20,1) ); -- 结果:123.3

 

有细心的小伙伴应该能发现两个结果不一样, 因为我把例2 的decimal的精度改为1 , 所以cast会先进行一个四舍五入然后再进行转换操作.

convert和cast 一样也会四舍五入 就不在花篇幅了.

convert(参数 using 字符集)

例:

select convert('gbk' using utf8); -- 结果:gbk

 

没有效果是因为函数的作用只是修改字符集,但是内容是不变的  所以看起来没感觉

left函数及扩展right函数和SUBSTRING、SUBSTRING_index

  1. left(字符串,截取多少个)  :从左侧截取
  2. right(字符串,截取多少个)  从右侧截取
  3. SUBSTRING(字符串,从哪个位置截取,截取多少个)
  4. substring_index(被截取字符串,关键字,关键字出现的次数)   关键字:检索匹配的条件     关键字出现的次数 n: 正数截取到第n个关键字 负数:从倒数第n个关键字开始截取  如果关键字在被截取的字符串中不存在则完整返回截取的字符串

例:后边的注释为结果

select left('12345678',2);  -- 结果:12

select right('12345678',2);  -- 结果:78

select SUBSTRING('12345678',2,3);  -- 结果:234

select substring_index('12324256278',22,-1); -- 结果:12324256278

select substring_index('12324256278',2,-1); -- 结果:78

select substring_index('12324256278',2,3); -- 结果:12324

HEX函数

hex(参数)将参数转换为16进制  如果参数是数字且不是整数会先进行四舍五入然后转16进制

例:这里的‘abc’ 应该是我本地的编码对应的值 , 如果本地不是编码abc对应的支不是97、98、99 则得到结果应该就不是616263了.

这个结论是不是正确我没有求证,如果哪位知道 还望指点, 但我本地的结果是这样的

SELECT HEX('abc'); ---》 先得到a,b,c的ascii码97, 98, 99再将其转为16进制 , 得到结果:616263

CONV函数

CONV(参数,原进制,目标进制);  将指定进制的参数转换为另一种进制

例:

select conv('a' , 16,10); -- 结果:10
select conv('2' , 10,2); -- 结果:10 这是二进制的1 0 
select conv('11000' , 2,16);-- 结果:18

INTERVAL函数

INTERVAL(n, n1,n2,n3,n4,n5); 返回最小大于n 的值的索引 n1 -》0 n2-》1

例:

select INTERVAL(2,4,6,8,10,34,56);  -- 结果: 0
select INTERVAL(6,4,6,8,10,34,56);  -- 结果: 2
select INTERVAL(66,4,6,8,10,34,56); -- 结果: 6

elt函数

elt(n,'字符串1','字符串2','字符串3','字符串4','字符串5','字符串6','字符串7');  返回指定索引的值  索引从1 开始 索引越界的返回null

例:

select elt(1,'字符串1','字符串2','字符串3','字符串4','字符串5','字符串6','字符串7');  字符串1
select elt(0,'字符串1','字符串2','字符串3','字符串4','字符串5','字符串6','字符串7');  null
select elt(10,'字符串1','字符串2','字符串3','字符串4','字符串5','字符串6','字符串7');  null

至此上边的所有的函数都以清楚,回过头看sql

 select  *
 FROM 表名
 order by  ELT(
 INTERVAL(
 CONV(
 HEX(left(CONVERT(字段名 USING gbk),1)),
 16,10),     
0xB0A1,0xB0C5,0xB2C1,0xB4EE,0xB6EA,0xB7A2,0xB8C1,0xB9FE,0xBBF7,     
0xBFA6,0xC0AC,0xC2E8,0xC4C3,0xC5B6,0xC5BE,0xC6DA,0xC8BB,0xC8F6,
0xCBFA,0xCDDA,0xCEF4,0xD1B9,0xD4D1),     
'A','B','C','D','E','F','G','H','J','K','L','M','N','O','P','Q','R','S','T','W','X','Y','Z') asc

过程是

得到字段首先将字符集转为gbk获得最左侧的字符,得到16进制的值 ,将16进制转换为10进制 然后通过interval获得对应的索引值. 最后通过elt函数得到对应的首字母;

其中两处标红的地方:

  1. 转为gbk的原因是gbk是根据康熙字典来的 所以本身就是根据拼音排好的序 
  2. 将16进制转换为10进制 这一步也许会有同学疑惑 通过hex函数转换后的结果不是已经是16进制了吗?直接进行16interval的函数转换不行吗? 

这里我们通过一个例子就能明白

例:

select HEX('c') - 17; -- 结果:46

还记得之前hex的例子吗?

SELECT HEX('abc'); -- 结果:616263

16进制的 63-17 应该等于52才对 可是结果确是46 很明显mysql的hex函数只是将进制转换

但是interval函数处理参数的时候可不会看你是不是hex函数返回的16进制 他只看数值所以他就认为是十进制跟后边比较得出的结果必然是错误的.

那我们希望是正确的值进行计算怎么办?所以conv函数上场

例:

select conv(HEX('c'),16,10) - 17; -- 结果:82

'c'的16进制我们之前已经得到了63, 而'c'对应的accII码为97  , 97-17 = 82 正确

到此 这个根据省份排序的sql查询逻辑已经明了.

但是我发现一个问题,就是多音字!!! 但是好消息是我国的省份只有直辖市  重庆是多音字 

例:

select 
elt(INTERVAL(CONV(HEX(left(CONVERT('重庆' USING gbk),1)),16,10),     
0xB0A1,0xB0C5,0xB2C1,0xB4EE,0xB6EA,0xB7A2,0xB8C1,0xB9FE,0xBBF7,     
0xBFA6,0xC0AC,0xC2E8,0xC4C3,0xC5B6,0xC5BE,0xC6DA,0xC8BB,0xC8F6,
0xCBFA,0xCDDA,0xCEF4,0xD1B9,0xD4D1),'A','B','C','D','E','F','G','H','J','K','L','M','N','O','P','Q','R','S','T','W','X','Y','Z') 

结果:上图更有说服力 哈哈

结果得到首字母为Z 估计是任务它读zhong吧

不幸中之大幸是只有一个,所以我是这么做的 判断下如果是重字替换成没有多音的字且和重(chong)首字母相同就行了

select 
elt(INTERVAL(CONV(HEX(case  left(CONVERT('重庆' USING gbk),1) when '重' then '葱' else left(CONVERT('重庆' USING gbk),1) end ),16,10),     
0xB0A1,0xB0C5,0xB2C1,0xB4EE,0xB6EA,0xB7A2,0xB8C1,0xB9FE,0xBBF7,     
0xBFA6,0xC0AC,0xC2E8,0xC4C3,0xC5B6,0xC5BE,0xC6DA,0xC8BB,0xC8F6,
0xCBFA,0xCDDA,0xCEF4,0xD1B9,0xD4D1),'A','B','C','D','E','F','G','H','J','K','L','M','N','O','P','Q','R','S','T','W','X','Y','Z') 

结果:

最终的sql为:

select  *
 FROM 表名
 order by  ELT(
 INTERVAL(
 CONV(
 HEX(case  left(CONVERT(字段名 USING gbk),1) when '重' then '葱' else left(CONVERT(字段名 USING gbk),1) end  ),
 16,10),     
0xB0A1,0xB0C5,0xB2C1,0xB4EE,0xB6EA,0xB7A2,0xB8C1,0xB9FE,0xBBF7,     
0xBFA6,0xC0AC,0xC2E8,0xC4C3,0xC5B6,0xC5BE,0xC6DA,0xC8BB,0xC8F6,
0xCBFA,0xCDDA,0xCEF4,0xD1B9,0xD4D1),     
'A','B','C','D','E','F','G','H','J','K','L','M','N','O','P','Q','R','S','T','W','X','Y','Z') asc

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值