Linux——MySQL内置函数与复合查询
内置函数
日期函数
获得年月日:
获得时分秒:
获得时间戳:
返回日期部分:
在日期的基础上加日期:
在日期的基础上减去时间:
计算两个日期之间相差多少天:
新中国成立了多少天:
使用案例
创建一个生日表
如果插入一个current_time()也是可以的:
时间戳也可以:
这里相当于一个隐式类型转换,只截取了自己需要的内容。
但是最好这样写:
这样更容易让人读懂。
创建一个留言表
显示所有留言信息,发布日期只显示日期,不用显示时间:
请查询在2分钟内发布的帖子:
就是按照当前时间减去两分钟查看表中是否有时间是否符合。也就是筛选表中时间+两分钟是否大于现在时间。
字符串函数
charset(str) | 返回字符串字符集 |
---|---|
concat(string2,…]) | 连接字符串 |
instr(string,substring) | 返回substring在string中出现的位置,没有返回0 |
ucase(string2)) | 转换成大写 |
lcase(string2) | 转换成小写 |
left(string2,length) | 从string2中的左边起取length个字符 |
length(string) | string的长度 |
replace(str,search str,replace str) | 在str中用replace_str替换search str |
strcmp(stringl, string2) | 逐字符比较两字符串大小 |
substring(str,position ,length]) | 从str的postion开始,取length个字符 |
ltrim(string)rtrim(string)trim(string) | 去除前空格或后空格 |
使用案例
获取emp表的ename列的字符集(获取某一列指定的编码格式)
这里再次使用oracle 9i的经典测试表来进行案例使用。
要求显示exam_result表中的信息,显示格式:“XXX的语文是XXX分,数学XXX分,英语XXX分”
求学生表中学生姓名占用的字节数
因为是utf8,一个汉字占三个字节。
注意:length函数返回字符串长度,以字节为单位。如果是多字节字符则计算多个字节数;
如果是单字节字符则算作一个字节。比如:字母,数字算作一个字节,中文表示多个字节数(与字符集编码有关)
将EMP表中所有名字中有S的替换成’上海’
这里并不是真正的对库进行操作,原本库中的表并没有进行改变。
截取EMP表中ename字段的第二个到第三个字符
以首字母小写的方式显示所有员工的姓名
去除空格
数学函数
函数名称 | 描述 |
---|---|
abs (number) | 绝对值函数 |
bin (decimal number) | 十进制转换二进制(浮点数会取整) |
hex(decimalNumber) | 转换成十六进制 |
conv(number,from base,to base) | 进制转换(第一个是要转换的数,第二个是被转换进制,第三个是要转换的进制) |
ceiling(number) | 向上去整 |
floor (number) | 向下去整 |
format(number,decimal places) | 格式化,保留小数位数 |
rand() | 返回随机浮点数,范围[0.0,1.0) |
mod (number, denominator) | 取模,求余 |
向上取整与向下取整
取整有很多种方式:
舍弃掉小数位,无论是整数还是负数都是向0靠近的,所以也叫做零向取整。
那么向上取整其实就是根据这个数轴的方向向上面取整。
那么向下取整也就好理解了
注意,这里不要和四舍五入搞混,小数部分无论是多少都没关系。
其它函数
user() 查询当前用户
md5(str)对一个字符串进行md5摘要,摘要后得到一个32位字符串
database()显示当前正在使用的数据库
password()函数,MySQL数据库使用该函数对用户加密
ifnull(val1, val2) 如果val1为null,返回val2,否则返回val1的值
复合查询
对一张表进行查询,在实际开发中这远远不够。
简单认识子查询
显示工资高于平均工资的员工信息
这里想查询结果,分成两步:
先查询最高工资
再通过得到的最高工资信息来继续查询
这样写起来太麻烦了,所以可以合二为一,在where当中再加一个select,叫做子查询。
多表查询
实际开发中往往数据来自不同的表,所以需要多表查询。本节我们用一个简单的公司管理系统,有三张表EMP,DEPT,SALGRADE来演示如何进行多表查询。
显示雇员名、雇员工资以及所在部门的名字因为上面的数据来自EMP和DEPT表,因此要联合查询
员工名和员工工资在emp表,部门在dept表。
组合的条件里有很多信息是无意义的,要再次进行筛选。
显示部门号为10的部门名,员工名和工资
显示各个员工的姓名,工资,及工资级别
这里工资级别是在salgrade这张表里。
自连接
自连接是指在同一张表连接查询,也就是说将一张表做笛卡尔积
显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号–empno)
上面说过一个子查询,所以第一种方法可以用子查询的方式解决问题:
另一种方式就是自查询:
首先让这个表进行自己和自己笛卡尔积。
e1和e2时emp表的别名。
然后在根据笛卡尔积的结果筛选出要查询的结果。
子查询
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。
单行子查询
返回一行记录的子查询——显示SMITH同一部门的员工
select * from emp where deptno = (select deptno from emp where ename=‘smith’);
括号里先查询的是SMITH在哪个部门,然后括号外部在emp表中查询所有部门和括号内的信息进行对比。
多行子查询
返回多行记录的子查询:
in关键字;查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自
己的
select ename,job,sal,deptno from emp where job in (select distinct job from emp where deptno=10) and deptno<>10;
括号里是取到10号部门的工作岗位信息,然后让emp表中的job根据括号中的信息做对比,最后进行最后的对比,不等于10号部门,也就是排除了10号部门。
all关键字(all是所有人的意思);显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
这里意思是,大于30部门最高工资的人还要高。
可以先找出来30部门最高工资的人,然后找出emp中比他高的。
也可以使用all,从emp表中找出比all当中的人都高。
any关键字;显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门
的员工)
这里意思是任意一人,那么30号部门最低工资的人也是任意一人的其中一员,所以只要工资比他高就可以了。
多列子查询
单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询则是指查询返回多个列数据的子查询语句。
查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人
红框当中其实也可以用in。
在from子句中使用子查询
子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。
显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资
这里说的是高于自己部门的平均工资,所以说首先要弄出各个部门的平均工资,在from后面弄出一个笛卡尔积的临时表。
然后再通过查询这个临时表中高于自己部门平均工资的人。
查找每个部门工资最高的人的姓名、工资、部门、最高工资
显示每个部门的信息(部门名,编号,地址)和人员数量
方法1:使用多表:
按 dept.deptno(部门编号)分组;
在相同 dept.deptno 下,继续按 dept.dname(部门名称)分组;
在相同 dept.deptno 和 dept.dname 下,再按 dept.loc(部门位置)分组。
这里是因为照顾group by的语法设计,所以后面多了很多字段。
方法2:使用子查询:(其实也算是多表,因为mysql下一切皆表)
总结:解决多表问题的本质——想办法将多表转化成为单表,所以musql中,所有的select的问题全部可以转换成单表问题。
这就是多表查询的思想。
合并查询
在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。
两边的列数必须是一样的。
union
该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
将工资大于2500或职位是MANAGER的人找出来
union all
该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。
将工资大于25000或职位是MANAGER的人找出来
内外链接
内连接
内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,我们前面学习的查询都是内连接,也是在开发过程中使用的最多的连接查询。
select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件;
之前的内连接是:
显示SMITH的名字和部门名称
select ename, dname from emp, dept where emp.deptno=dept.deptno and ename=‘SMITH’;
select ename, dname from emp inner join dept on emp.deptno=dept.deptno and ename=‘SMITH’;
外连接
左外连接
如果联合查询,左侧的表完全显示(左边的表不会进行任何的过滤和筛选)我们就说是左外连接。
select 字段名 from 表名1 left join 表名2 on 连接条件;
先创建两个表进行演示
查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出来
右外连接
如果联合查询,右侧的表完全显示我们就说是右外连接。
select 字段 from 表名1 right join 表名2 on 连接条件;
对stu表和exam表联合查询,把所有的成绩都显示出来,即使这个成绩没有学生与它对应,也要显示出来
列出部门名称和这些部门的员工信息,同时列出没有员工的部门