mysql> select * from emp where (sal > 500 or job = 'MANAGER') and ename like 'J%';
也可以使用内置函数来查询首字母为大写的J
mysql> select * from emp where (sal > 500 or job = 'MANAGER') and
-> substring(ename, 1, 1) = 'J';
mysql> select * from emp order by deptno asc, sal desc;
年薪 = 月薪(sal) * 12 + 奖金(comm)
直接用comm的NULL参与运算
正确写法:
mysql> select ename, sal*12+ifnull(comm,0) as 年薪 from emp order by 年薪 desc;
解决该问题有两种方案:
两次查询
mysql> select max(sal) from emp;
mysql> select ename, job from emp where sal = '5000';
一次子查询,将两条查询语句合并起来,where条件筛选中再使用select进行筛选,此语句执行的顺序是由内向外,先执行where中的select,再执行整句中的select
mysql> select ename, job from emp where sal = (select max(sal) from emp);
同样使用子查询
mysql> select * from emp where sal > (select avg(sal) from emp);
在group by子句中指明按照部门号进行分组,在select语句中使用avg函数和max函数,分别查询每个部门的平均工资和最高工资
mysql> select deptno, format(avg(sal),2), max(sal) from emp group by deptno;
在group by子句中指明按照部门号进行分组,在select语句中使用avg函数查询每个部门的平均工资,在having子句中指明筛选条件为平均工资小于2000
mysql> select deptno, avg(sal) as 平均工资 from emp group by deptno having 平均工资 < 2000;
mysql> select job, count(*), format(avg(sal),2) from emp group by job;
实际开发中往往数据来自不同的表,所以需要多表查询。本节我们用一个简单的公司管理系统,有三张表EMP, DEPT, SALGRADE 来演示如何进行多表查询。
员工表:
部门表:
我们想让两个表联合显示为一张表
mysql> select * from emp, dept;
我们会发现上面的表是这样显示的
整张表由两个表构成,前半部分是员工表的列信息,后半部分是部门表的列信息。
同时员工表中每条记录与部门表进行穷举组合,员工表中的每一个员工信息都会和部门表中的每一个部门信息进行组合。
我们这种从第一张表中选取一条记录与第二张表中的所有记录进行穷举组合且不加过滤条件,得到的结果称为笛卡尔积。
但是在实际开发中,一个员工只有和自己所在的部门信息进行组合才是有意义的,因此需要我们在笛卡尔积产生的新表中筛选出真正需要的数据
笛卡尔积的表中可能会存在相同的列名,这时在选中列名时需要通过表名.列名
的方式进行指明,若有重复的不指明确切的一列,就会报错
mysql> select ename,sal,dname from emp, dept where emp.deptno = dept.deptno;
mysql> select ename, sal, emp.deptno, dname from emp, dept where dept.deptno=emp.deptno and dept.deptno = 10;
mysql> select ename, sal, grade from emp, salgrade where sal between losal and hisal;
自连接是指在同一张表连接查询,即我们可以对同一张表取笛卡尔积
可以分为2步:
这2步合并为1步使用子查询
mysql> select empno, ename from emp where empno = (select mgr from emp where ename = 'FORD');
对同一张表做笛卡尔积要给自己的表起别名
mysql> select * from emp e1, emp e2;
mysql> select e2.empno, e2.ename from emp e1, emp e2 where e1.ename='FORD'
-> and e1.mgr = e2.empno;
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询
返回一行记录的子查询
在子查询中查询SMITH所在的部门号,在where子句中指明筛选条件为员工部门号等于子查询返回的部门号
mysql> select * from emp where deptno = (select deptno from emp where ename = 'SMITH');
返回多行记录的子查询
in关键字: 判断某个对应列值是否在集合当中
可以先查询10号部门有哪些岗位,查询时要对结果进行去重,因为10号部门的某些员工的工作岗位可能是相同的
再将上述查询作为子查询,在查询员工表时在where子句中使用in关键字,判断员工的工作岗位是子查询得到的若干岗位中的一个
mysql> select ename,job,sal, deptno from emp where job in(select distinct job from emp where deptno = 10) and deptno<>10;
拿着查询出来的表结构和其他查询结果做笛卡尔积
mysql> select ename, job,sal,dname from(select ename,job,sal, deptno from emp where job in(select distinct job from emp where deptno = 10) and deptno<>100) as tmp, dept where dept.deptno=tmp.deptno;
all关键字
mysql> select ename,sal,deptno from emp where sal > all(select distinct sal from emp where deptno = 30);
any关键字
mysql> select ename,sal,deptno from emp where sal > any(select distinct sal from emp where deptno = 30);
单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询则是指查询返回多个列数据的子查询语句
mysql> select * from emp where (deptno, job) = (select deptno, job from emp where ename ='SMITH') and ename<>'SMITH';
#这里也可以把=改成in
mysql> select * from emp where (deptno, job) in (select deptno, job from emp where ename ='SMITH') and ename<>'SMITH';
上面除(2)外所有的子查询,全部在where子句中,充当判断条件
任何时候,查询出来的临时结构,本质在逻辑上也是表结构,即MySQL中一切皆表
子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。
多表查询的指导思想:
解决多表问题的本质:想办法将多表转化成单表,所以MySQL中,所有select的问题全部都可以转成单表问题
# 显示每个部门的平均工资,将其看作临时表
mysql> select deptno, avg(sal) mysal from emp group by deptno;
# 多表查询
mysql> select * from emp, (select deptno, avg(sal) mysal from emp group by deptno) tmp
-> where sal > tmp.mysal and emp.deptno=tmp.deptno;
# 单表查询
mysql> select ename,emp.deptno,sal,mysal from emp, (select deptno, avg(sal) mysal from emp group by deptno) tmp where sal > tmp.mysal and emp.deptno=tmp.deptno;
mysql> select * from dept;
# 多表查询
mysql> select * from dept, (select ename,emp.deptno,sal,mysal from emp, (select deptno,
-> avg(sal) mysal from emp group by deptno) tmp where sal > tmp.mysal and
-> emp.deptno=tmp.deptno) t1;
mysql> select * from dept, (select ename,emp.deptno,sal,mysal from emp, (select deptno,
-> avg(sal) mysal from emp group by deptno) tmp where sal > tmp.mysal and
-> emp.deptno=tmp.deptno) t1 where t1.deptno=dept.deptno;
# 单表查询
mysql> select t1.ename,dept.loc,t1.deptno from dept, (select ename,emp.deptno,sal,mysal
-> from emp, (select deptno, avg(sal) mysal from emp group by deptnoo) tmp where sal
-> > tmp.mysal and emp.deptno=tmp.deptno) t1 where t1.deptno=dept.deptno;
# 每个部门的最高工资
mysql> select deptno, max(sal) from emp group by deptno;
# 多表查询
mysql> select * from emp e1, (select deptno, max(sal) from emp group by deptno) e2;
mysql> select * from emp e1, (select deptno, max(sal) mysal from emp group by deptno) e2 where e1.deptno=e2.deptno and e1.sal=e2.mysal;
# 单表查询
mysql> select ename, sal, e1.deptno, mysal from emp e1, (select deptno, max(sal) mysal
-> from emp group by deptno) e2 where e1.deptno=e2.deptno and e1.sal=e2.mysal;
# 每个部门的人数
mysql> select deptno, count(*) dept_num from emp group by deptno;
# 多表查询
mysql> select * from dept t1, (select deptno, count(*) dept_num from emp group by deptno)
-> t2 where t1.deptno=t2.deptno;
# 单表查询
mysql> select dname,t1.deptno,loc, dept_num from dept t1, (select deptno, count(*)
-> dept_num from emp group by deptno) t2 where t1.deptno=t2.deptno;
在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all
该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
mysql> select * from emp where job='MANAGER';
mysql> select * from emp where sal > 2500 union select * from emp where job='MANAGER';
mysql> select * from emp where sal > 2500 union select * from emp where job='MANAGER';
该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。
mysql> select * from emp where sal > 2500 union all select * from emp where job = 'MANAGER';