-- 分组有多个部门,每个部门的平均工资-- HAVING 对分组之后的结果进行判断SELECT deptno, AVG(sal) AS 平均工资 FROM emp GROUPBY deptno HAVING 平均工资 <2000;
显示每种岗位的雇员总数,平均工资
SELECT job, COUNT(job) AS 人数, FORMAT(AVG(sal), 2) AS 平均工资 FROM emp GROUPBY job;
多表笛卡尔积
两张表进行组合,第一张表中的第一条信息和第二张表中的 4 条信息进行组合/穷举
显示雇员名、雇员工资以及所在部门的名字
-- 连接两张表进行查询SELECT ename, sal, dname FROM dept, emp WHERE emp.deptno = dept.deptno;
显示部门号为 10 的部门名,员工名和工资
SELECT ename, sal, dname, dept.deptno FROM emp, dept WHERE emp.deptno = dept.deptno AND emp.deptno =10;
显示各个员工的姓名,工资,及工资级别
SELECT ename, sal, grade, losal, hisal FROM emp, salgrade WHERE sal BETWEEN losal AND hisal;
自连接
用同一张表进行笛卡尔积,但是要进行重命名
显示员工 FORD 的上级领导的编号和姓名(mgr 是员工领导的编号–empno)
先找 FORD 的领导编号
根据领导编号找领导的信息
SELECT ename, empno FROM emp WHERE empno = (SELECT mgr FROM emp WHERE ename ='FORD');
SELECT e2.ename, e2.empno FROM emp e1, emp e2 WHERE e1.ename ='FORD'AND e1.mgr = e2.empno;
子查询与 where
子查询
子查询是指嵌入在其他 SQL 语句中的 SELECT 语句,也叫嵌套查询
单行子查询
返回一行记录的子查询
显示 SMITH 同一部门的员工
SELECT*FROM emp WHERE deptno = (SELECT deptno FROM emp WHERE ename ='SMITH');
多行子查询
返回多行记录的子查询
IN 关键字,判断集合是否在列当中
查询和 10 号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含 10 自己的
SELECT ename, job, sal, deptno FROM emp WHERE job IN (SELECTDISTINCT job FROM emp WHERE deptno =10) AND deptno <>10;
并且知道对应的员工属于哪个部门的名字
SELECT ename, job, sal, dname
FROM (SELECT ename, job, sal, deptno FROM emp WHERE job IN (SELECTDISTINCT job FROM emp WHERE deptno =10) AND deptno <>10) AS tmp, dept
WHERE dept.deptno = tmp.deptno;
ALL 关键字;显示工资比部门 30 的所有员工的工资高的员工的姓名、工资和部门号
SELECT*FROM emp WHERE sal > (SELECTMAX(sal) FROM emp WHERE deptno =30);
ALL,比所有人的工资都高,就是比 30 号部门最高工资都高
SELECT*FROM emp WHERE sal >ALL (SELECTDISTINCT sal FROM emp WHERE deptno =30);
ANY 关键字;显示工资比部门 30 的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)
任意指的是,比该部门中最小的大都行
SELECT*FROM emp WHERE sal >ANY (SELECTDISTINCT sal FROM emp WHERE deptno =30);
SELECT*FROM emp WHERE (deptno, job) = (SELECT deptno, job FROM emp WHERE ename ='SMITH') AND ename <>'SMITH';
总结:
目前全部的子查询,全部都在 WHERE 子句中,充当判断条件
任何时候查询出来的逻辑结构,本质上在逻辑上也是表结构
子查询不仅可以出现在 WHERE 后面,也可以出现在 FROM 后面(把子查询当成一个临时表使用)
子查询与 from
子查询语句出现在 FROM 子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。
案例
显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资
-- 查询分组后的部门号和平均工资SELECT deptno, AVG(sal) FROM emp GROUPBY deptno;
-- 对员工表和部门的平均工资表做拼接-- 做笛卡尔积要部门号相同才有意义SELECT*FROM emp, (SELECT deptno, AVG(sal) FROM emp GROUPBY deptno) AS tmp WHERE emp.deptno = tmp.deptno;
SELECT*FROM emp, (SELECT deptno, AVG(sal) AS myavg FROM emp GROUPBY deptno) AS tmp WHERE emp.deptno = tmp.deptno AND emp.sal > tmp.myavg;
在加一个条件,筛选出部门号和办公地点,要连接部门表和这个临时表
查找每个部门工资最高的人的姓名、工资、部门、最高工资
SELECT ename, sal, t1.deptno, mymax FROM emp AS t1, (SELECT deptno, MAX(sal) AS mymax FROM emp GROUPBY deptno) AS t2 WHERE t1.deptno = t2.deptno AND t1.sal = t2.mymax;
显示每个部门的信息(部门名,编号,地址)(dept)和人员数量
SELECT t1.deptno, t1.dname, t1.loc, t2.dept_num FROM dept AS t1, (SELECT deptno, COUNT(*) AS dept_num FROM emp GROUPBY deptno) AS t2 WHERE t1.deptno = t2.deptno;
COUNT(*) 是聚合函数,所以不需要在 GROUP BY 里出现。
在标准 SQL(如 MySQL 5.7+、PostgreSQL、SQL Server)中,SELECT 子句中的所有非聚合列(如 DEPT.dname, DEPT.loc)必须出现在 GROUP BY 子句中,否则会报错。