MySQL 复合复合查询及内置函数详解
MySQL复合查询
1. 内置函数
1.1 日期函数
函数名称 | 描述 |
---|---|
current_date() | 当前日期 |
current_time() | 当前时间 |
current_timestamp() | 当前时间戳 |
date(datetime) | 返回 datetime 参数的日期部分 |
date_add(date , interval d_value_type) | 为 date 日期时间添加日期或时间 interval后的数字单位可以是:year minute second day |
date_sub(date , interval d_value_type) | 为 date 日期时间减去日期或时间 interval后的数字单位可以是:year minute second day |
datediff(date1 , date2) | 两个日期的差,单位是天 |
now() | 当前日期时间 |
- 日期:2025-09-24
- 日期时间:2025-09-24 19:29:30
1.2 字符串函数
函数名称 | 描述 |
---|---|
charset(str) | 返回字符串的字符集 |
concat(string , […]) | 拼接字符串 |
instr(str , substr) | 返回 substr 在 str 中出现的位置,下标从1开始,不存在返回0 |
ucase(str) | 转换为大写 |
lcase(str) | 转换为小写 |
left(str , len) | 从 str 左边取 len 个字符 |
length(str) | str 的长度 |
replace(str , src_str , replace_str) | 将 str 中的 src_str 子串替换为 replace_str |
strcmp(str1 , str2) | 比较两个字符串大小 |
substring(str , pos , len) | 从 str 的 pos 位置开始取 len 个字符 |
ltrim(str)、rtrim(str)、trim(str) | 去除前后空格 |
1.3 数学函数
函数名称 | 描述 |
---|---|
abs(num) | 取绝对值 |
bin(decimal_num) | 十进制转二进制 |
hex(decimal_num) | 十进制转十六进制 |
conv(num , from_base , to_base) | from_base 进制转换 to_base 进制 |
ceiling(num) | 向上取整 |
floor(num) | 向下取整 |
format(num , decimal_places) | 保留小数 decimal_places 位 |
rand() | 返回随机浮点数,范围[0.0 , 1.0] |
mod(number , denominator) | 取模 |
1.4 其他函数
函数名称 | 描述 |
---|---|
user() | 查询当前用户 |
md5(str) | 对一个字符串进行md5摘要,摘要后得到一个32位字符串 |
datebase() | 显示当前正在使用的数据库 |
password() | MySQL数据库使用该函数对用户加密 |
ifnull(val1 , val2) | 如果 val1 为 null,返回 val2,否则返回 val1 |
注意:可通过 select 使用函数。格式:select function();
2. 复合查询
2.1 准备工作(Oracle 9i经典测试表)
DROP database IF EXISTS `scott`;
CREATE database IF NOT EXISTS `scott` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;USE `scott`;DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (`deptno` int(2) unsigned zerofill NOT NULL COMMENT ' 部门编号 ',`dname` varchar(14) DEFAULT NULL COMMENT ' 部门名称 ',`loc` varchar(13) DEFAULT NULL COMMENT ' 部门所在地点 '
);DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (`empno` int(6) unsigned zerofill NOT NULL COMMENT '雇员编号',`ename` varchar(10) DEFAULT NULL COMMENT '雇员姓名',`job` varchar(9) DEFAULT NULL COMMENT '雇员职位',`mgr` int(4) unsigned zerofill DEFAULT NULL COMMENT '雇员领导编号',`hiredate` datetime DEFAULT NULL COMMENT '雇佣时间',`sal` decimal(7,2) DEFAULT NULL COMMENT '工资月薪',`comm` decimal(7,2) DEFAULT NULL COMMENT '奖金',`deptno` int(2) unsigned zerofill DEFAULT NULL COMMENT '部门编号'
);DROP TABLE IF EXISTS `salgrade`;
CREATE TABLE `salgrade` (`grade` int(11) DEFAULT NULL COMMENT '等级',`losal` int(11) DEFAULT NULL COMMENT '此等级最低工资',`hisal` int(11) DEFAULT NULL COMMENT '此等级最高工资'
);insert into dept (deptno, dname, loc)
values (10, 'ACCOUNTING', 'NEW YORK');
insert into dept (deptno, dname, loc)
values (20, 'RESEARCH', 'DALLAS');
insert into dept (deptno, dname, loc)
values (30, 'SALES', 'CHICAGO');
insert into dept (deptno, dname, loc)
values (40, 'OPERATIONS', 'BOSTON');insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, null, 20);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, null, 30);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, null, 10);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, null, 20);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7839, 'KING', 'PRESIDENT', null, '1981-11-17', 5000, null, 10);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7844, 'TURNER', 'SALESMAN', 7698,'1981-09-08', 1500, 0, 30);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, null, 20);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, null, 30);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, null, 20);insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, null, 10);insert into salgrade (grade, losal, hisal) values (1, 700, 1200);
insert into salgrade (grade, losal, hisal) values (2, 1201, 1400);
insert into salgrade (grade, losal, hisal) values (3, 1401, 2000);
insert into salgrade (grade, losal, hisal) values (4, 2001, 3000);
insert into salgrade (grade, losal, hisal) values (5, 3001, 9999);
创建 xxx.sql 文件,将上述内容拷贝至 xxx.sql 文件。
在 mysql 中输入 source xxx.sql;
2.2 基本查询
2.2.1 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J
select * from emp where (sal > 500 or job = "MANAGER") and left(ename , 1) = "J";
2.2.2 按照部门号升序而雇员的工资降序排序
select * from emp order by deptno asc , sal desc;
2.2.3 使用年薪进行降序排序
select ename , sal * 12 + ifnull(comm , 0) as "年薪" from emp order by 年薪 desc;
2.2.4 显示工资最高的员工的名字和工作岗位
select ename , job from emp where sal = (select max(sal) from emp);
2.2.5 显示每个部门的平均工资和最高工资
select deptno , format(avg(sal) , 2) , max(sal) from emp group by deptno;
2.2.6 显示平均工资低于2000的部门号和它的平均工资
select deptno , avg(sal) from emp group by deptno having avg(sal) < 2000;
2.3 笛卡尔积
如果表A有N行,表B有M行,笛卡尔积的结果是 N * M 行。
将第一张表中的第一条记录和第二张表的所有记录进行组合,将第一张表中的第二条记录和第二张表的所有记录进行组合,以此类推。
通过 select * from emp , dept where emp.deptno = dept.deptno 过滤没有意义的行。
2.3.1 显示部门号为10的部门名,员工名和工资
select dname , ename , sal from emp , dept where emp.deptno = dept.deptno and dept.deptno = 10;
2.3.2 显示各个员工的姓名,工资,及工资级别
select ename , sal , hisal from emp , salgrade where sal between losal and hisal;
2.4 自连接
自连接是指在同一张表连接查询。
2.4.1 显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号–empno)
使用子查询:
select deptno , ename from emp where empno = (select mgr from emp where ename = "FORD");
使用多表查询:
select t1.empno , t1.ename from emp as t1, emp as t2 where t1.empno = t2.mgr and t2.ename = "FORD";
2.5 子查询(嵌套查询)
子查询是指嵌入在其他 sql 语句中的select语句,也叫嵌套查询。通常嵌入在 from 和 where 后。
2.5.1 单行单列子查询
返回一行记录的子查询。
-
显示SMITH同一部门的员工
select ename from emp where deptno = (select deptno from emp where ename = "SMITH");
2.5.2 多行单列子查询
返回多行记录的子查询
-
in 关键字:查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的
select ename , job , sal , deptno from emp where job in (select distinct job from emp where deptno = 10) and deptno != 10;
-
all关键字;显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
select ename , sal , deptno from emp where sal > (select max(sal) from emp where deptno = 30);
select ename , sal , deptno from emp where sal > all (select sal from emp where deptno = 30);
-
any关键字;显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)
select ename , sal , deptno from emp where sal > (select min(sal) from emp where deptno = 30);
select ename , sal , deptno from emp where sal > any(select sal from emp where deptno = 30);
2.5.3 多行多列子查询
查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人
select * from emp , (select deptno , job from emp where ename = "SMITH") as temp where emp.deptno = temp.deptno and emp.job = temp.job and ename != "SMITH";
select * from emp where (deptno , job) = (select deptno , job from emp where ename = "SMITH") and ename != "SMITH";
2.5.4 在 from 子句中使用子查询
上述大部分子查询 sql 都出现在 where 子句中。
子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。
-
显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资
select ename , emp.deptno , sal , temp.tempavg from emp , (select deptno , avg(sal) as tempavg from emp group by deptno) as temp where emp.deptno = temp.deptno and sal > tempavg;
-
查找每个部门工资最高的人的姓名、工资、部门、最高工资
select ename , sal , emp.deptno , max_sal from emp , (select deptno , max(sal) max_sal from emp group by deptno) as temp where emp.deptno = temp.deptno and sal = max_sal;
-
显示每个部门的信息(部门名,编号,地址)和人员数量
select dept.deptno dname , loc , num from dept , (select deptno , count(*) as num from emp group by deptno) as temp where dept.deptno = temp.deptno;
2.6 合并查询
2.6.1 union
该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
- 将工资大于2500或职位是MANAGER的人找出来
select ename, sal, job from emp where sal>2500 union select ename, sal, job from emp where job='MANAGER';
+-------+---------+-----------+
| ename | sal | job |
+-------+---------+-----------+
| JONES | 2975.00 | MANAGER |
| BLAKE | 2850.00 | MANAGER |
| SCOTT | 3000.00 | ANALYST |
| KING | 5000.00 | PRESIDENT |
| FORD | 3000.00 | ANALYST |
| CLARK | 2450.00 | MANAGER |
+-------+---------+-----------+
2.6.2 union all
该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。
- 将工资大于25000或职位是MANAGER的人找出来
select ename, sal, job from emp where sal>2500 union all select ename, sal, job from emp where job='MANAGER';
+-------+---------+-----------+
| ename | sal | job |
+-------+---------+-----------+
| JONES | 2975.00 | MANAGER |
| BLAKE | 2850.00 | MANAGER |
| SCOTT | 3000.00 | ANALYST |
| KING | 5000.00 | PRESIDENT |
| FORD | 3000.00 | ANALYST |
| JONES | 2975.00 | MANAGER |
| BLAKE | 2850.00 | MANAGER |
| CLARK | 2450.00 | MANAGER |
+-------+---------+-----------+