1、数据库
CREATE TABLE b_EMP
(
empno INT PRIMARY KEY AUTO_INCREMENT,
ename VARCHAR(50) NOT NULL,
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DOUBLE,
comm DOUBLE,
deptno INT,
CONSTRAINT fk_emp_deptno FOREIGN KEY(deptno) REFERENCES b_dept(deptno)
);
CREATE TABLE b_SALGRADE
(
grade INT,
losal INT,
hisal INT
);
INSERT INTO b_DEPT(deptno,dname,loc)
VALUES(10,‘市场部’,‘中国’);
INSERT INTO b_DEPT(deptno,dname,loc)
VALUES(20,‘研发部’,‘中国’);
INSERT INTO b_DEPT(deptno,dname,loc)
VALUES(30,‘行政部’,‘中国’)
INSERT INTO b_EMP
VALUES(7654, ‘MARTIN’, ‘SALESMAN’, 7698, NOW(), 1250, 1400, 30);
INSERT INTO b_EMP
VALUES(7698, ‘BLAKE’, ‘MANAGER’, 7839, NOW(), 2850, NULL, 30);
INSERT INTO b_EMP
VALUES(7782, ‘CLARK’, ‘MANAGER’, 7839, NOW(), 2450, NULL, 10);
INSERT INTO b_EMP
VALUES(7788, ‘SCOTT’, ‘ANALYST’, 7566, NOW(), 3000, NULL, 20);
INSERT INTO b_EMP
VALUES(7839, ‘KING’, ‘PRESIDENT’, NULL, NOW(), 5000, NULL, 10)
INSERT INTO b_EMP
VALUES(7844, ‘TURNER’, ‘SALESMAN’, 7698, NOW(), 1500, 0, 30);
INSERT INTO b_EMP
VALUES(7876, ‘ADAMS’, ‘CLERK’, 7788, NOW(), 1100, NULL, 20);
INSERT INTO b_EMP
VALUES(7900, ‘JAMES’, ‘CLERK’, 7698, NOW(), 950, NULL, 30);
INSERT INTO b_EMP
VALUES(7902, ‘FORD’, ‘ANALYST’, 7566, NOW(), 3000, NULL, 20);
INSERT INTO b_EMP
VALUES(7934, ‘MILLER’, ‘CLERK’, 7782, NOW(), 1300, NULL, 10);
INSERT INTO b_EMP
VALUES(7655, ‘kong11’, ‘MANAGER’, 7782, NOW(), 3300, 200, 10);
INSERT INTO b_EMP
VALUES(7656, ‘wang’, ‘ANALYST’, 7902, NOW(), 3600, 200, 30)
INSERT INTO b_EMP
VALUES(8000, ‘MARTIN’, ‘SALESMAN’, 7698, NOW(), 1250, 1400, NULL);
INSERT INTO b_EMP
VALUES(8001, ‘MARTIN’, ‘SALESMAN’, 7698, NOW(), 3600, 1400, 10);
INSERT INTO b_SALGRADE
VALUES(1,700,1200);
INSERT INTO b_SALGRADE
VALUES(2,1201,1400);
INSERT INTO b_SALGRADE
VALUES(3,1401,2000);
INSERT INTO b_SALGRADE
VALUES(4,2001,3000);
INSERT INTO b_SALGRADE
VALUES(5,30001,9999);
2、普通查询
#1、单表查询
#1) 查询所有员工信息
#2) 查询员工编号和员工名称
#3) 查询名称为SCOTT的员工记录
#4) 查询部门编号为10、20、30的员工记录
#5) 查询工资在1000到2000之间的员工记录
#6) 查询员工名称包含S的员工记录
#7) 查询奖金为NULL的员工记录
#8) 查询部门编号为10且职位为MANAGER的员工记录
#9) 查询部门编号为10或职位为MANAGER的员工记录
#10) 查询员工总人数
#11) 查询部门编号为10的工资总额
#12) 查询各部门的平均工资,最高工资,最低工资
3、SQL高级查询
多表查询
1、子查询
2、连接查询
2.1、内连接
2.1.1、等值连接查询
2.1.2、不等值连接查询
2.1.3、自然连接
2.2、外连接
2.2.1、左外连接
2.2.2、右外连接
2.3、自连接
2.4、交叉连接
3、联合查询
3.1、UNION
3.2、UNION ALL
3.3、INTERSECT
3.4、MINUS
1、子查询
- 查询与姓名为SCOTT在同一个部门的员工记录
SELECT * FROM b_emp WHERE deptno IN
(SELECT deptno FROM b_emp WHERE ename = 'kong11');
- 找出每个员工超过他所在部门平均工资的员工编号、名称、工资、部门编号
各个部门的平均工资
SELECT deptno,AVG(sal) FROM b_emp GROUP BY deptno;
1、SELECT empno,ename,sal,deptno
FROM b_emp e1 WHERE sal>(SELECT AVG(sal) FROM b_emp e2 WHERE e1.deptno=e2.deptno);
SELECT empno,ename,sal,e1.deptno
FROM b_emp AS e1,(SELECT AVG(sal)AS av,deptno FROM b_emp
GROUP BY deptno)e2 WHERE e1.`deptno` = e2.deptno AND e1.`sal`>e2.av
- 查询其他部门中比30号部门某一员工工资少的员工记录
<any 等价于 <max
<max
SELECT * FROM b_EMP WHERE deptno !=30 AND sal<(SELECT MAX(sal) FROM b_EMP WHERE deptno=30);
<any
SELECT * FROM b_EMP WHERE deptno !=30 AND sal<ANY(SELECT sal FROM b_EMP WHERE deptno=30);
=any 等价于 IN
SELECT * FROM b_EMP WHERE deptno !=30 AND sal=ANY(SELECT sal FROM b_EMP WHERE deptno=30);
<>all 等价于 NOT IN
<all 等价于 <min
- 查询员工工资大于3000的部门名称
SELECT DISTINCT dname FROM b_dept WHERE b_DEPT.deptno IN (
SELECT DISTINCT b_emp.deptno FROM b_emp WHERE b_emp.sal>3000);
exists():如果有查询结果就返回true,否则返回false,不关心到底查到了什么,只关心有没有结果
SELECT dname
FROM b_dept d
WHERE EXISTS(SELECT * FROM b_emp e WHERE e.deptno=d.deptno AND sal>3000);
2、连接查询
2.1、内连接
2.1.1、等值连接查询
查询员工编号、名称、部门编号、部门名称
SELECT empno,ename,e.deptno,dname
FROM b_emp e,b_dept d
WHERE e.`deptno`=d.`deptno`;
这2行效果等价
SELECT empno,ename,e.deptno,dname
FROM b_emp e INNER JOIN b_dept d ON e.`deptno`=d.`deptno`;
2.1.2、不等值连接查询
SELECT empno,ename,e.deptno,dname
FROM b_emp e,b_dept d
WHERE e.`deptno`<>d.`deptno`;
2.1.3、自然连接(不推荐使用,条件不清晰)
自然连接是在两张表中寻找哪些数据类型和列名相同的字段
然后自动地将它们连接起来,并返回符合条件主结果
不直接写WHERE条件,让数据自已去判断等值条件
SELECT empno,ename,e.deptno,dname
FROM b_emp e NATURAL JOIN b_dept d;
# 2.2、外连接
2.2.1、左外连接
左表的数据全部显示,右表的数据如果条件满足就显示出来,如果没有右表的数据与左表关联,则右表的数据显示为NULL
查询所有部门信息,如果有员工与其关联也显示员工记录
SELECT d.*,e.`empno`,e.`ename`
FROM b_dept d LEFT JOIN b_emp e ON d.`deptno`=e.`deptno`;
2.2.2、右外连接
右表的数据全部显示,左表的数据如果条件满足就显示出来,如果没有左表的数据与右表关联,则左表的数据显示为NULL
查询所有员工信息,如果员工与部门有关联则部门也显示出来,没有关联就显示为NULL
SELECT d.*,e.`empno`,e.`ename`
FROM b_dept d RIGHT JOIN b_emp e ON d.`deptno`=e.`deptno`;
2.3、自连接
查询员工编号,员工姓名和领导编号,领导姓名
SELECT e1.`empno` 员工编号,e1.`ename` 员工名称,e2.`empno` 领导编号,e2.`ename` 领导名称
FROM b_emp e1,b_emp e2
WHERE e1.`mgr`=e2.`empno`;
2.4、交叉连接
笛卡尔积:2张表查询,不带WHERE,返回结果为2张表的乘积
emp:13,dept:4==>13*4=52
SELECT * FROM b_dept,b_emp;
3、联合查询
3.1、UNION
对两个结果集进行并集操作,不包括重复行,同时进行默认排序
(将查询结果组合成一个结果,union过滤重复)
对联合查询排序是在最后一个结果集后指定order by子句
查询0到2000之间的工资
SELECT * FROM b_emp WHERE sal<1500
UNION
SELECT * FROM b_emp WHERE sal BETWEEN 1000 AND 2000
ORDER BY ename;
3.2、UNION ALL
对两个结果集进行并集操作,不过滤重复行,同时进行默认排序
(将查询结果组合成一个结果,union不过滤重复)
对联合查询排序是在最后一个结果集后指定order by子句
查询0到2000之间的工资
SELECT * FROM b_emp WHERE sal<1500
UNION ALL
SELECT * FROM b_emp WHERE sal BETWEEN 1000 AND 2000
ORDER BY ename;
3.3、不支持INTERSECTS:可以通过等值连接来解决
对两个结果集进行交集操作,不包括重复行,同时进行默认排序
返回2个结果集中相同的部分
SELECT a1.*
FROM
(SELECT * FROM b_emp WHERE sal<1500 ) a1,
(SELECT * FROM b_emp WHERE sal BETWEEN 1000 AND 2000) a2
WHERE a1.empno=a2.empno;
3.4、不支持MINUS:通过not in来替代MINUS解决
对两个结果集进行差操作,不包括重复行
返回第1个结果中与第2个结果集中不相同的那部分记录)
SELECT * FROM b_emp
WHERE sal<1500
AND empno NOT IN (SELECT empno FROM b_emp WHERE sal BETWEEN 1000 AND 2000)
4、使用正则表达式查询
SELECT * FROM b_emp;
查询以M开头的姓名
SELECT * FROM b_emp WHERE ename REGEXP ‘^M’;
查询以S结尾的姓名
SELECT * FROM b_emp WHERE ename REGEXP ‘S$’;
查询名称中包含SC或AM的员工记录
SELECT * FROM b_emp WHERE ename REGEXP ‘SC|AM’;
练习
#1.根据emp,dept表找出SCOTT所在部门名称和经理编号
SELECT mgr 经理编号,dname 部门名称 FROM b_emp e,b_dept d WHERE e.deptno
=d.deptno
AND e.ename=‘SCOTT’;
#2.根据emp,dept表列出没有对应部门表信息的所有雇员的姓名、工作及部门号。
如果emp没有外键约束
SELECT ename,job,deptno
FROM b_emp
WHERE deptno NOT IN (SELECT deptno FROM b_dept);
如果emp有外键约束
SELECT ename,job,deptno
FROM b_emp
WHERE deptno IS NULL
#3.根据emp,dept表求工资最高的雇员信息。
SELECT * FROM b_emp WHERE sal =(SELECT MAX(sal) FROM b_emp);
#4.根据emp,dept表求工资第二高的雇员信息(考虑并列情况)。
SELECT * FROM b_emp ORDER BY sal DESC;
第一种
SELECT *
FROM b_emp e INNER JOIN b_dept d ON e.deptno=d.deptno
WHERE sal=
(SELECT DISTINCT sal FROM b_emp ORDER BY sal DESC LIMIT 1,1);
第二种
SELECT b_emp.* FROM b_dept a2,b_emp WHERE sal =
((SELECT MAX(sal)AS a1 FROM b_emp,b_dept WHERE sal <(SELECT MAX(sal) FROM b_emp) AND b_emp.deptno
= b_dept.deptno
))
AND a2.deptno = b_emp.deptno
#5.根据emp,dept表求每个部门中工资最高的雇员信息。
SELECT * FROM b_emp ORDER BY deptno,sal DESC;
SELECT e1.* FROM b_emp e1,b_dept e2 WHERE e1.sal
=(SELECT MAX(sal) FROM b_emp e3 WHERE e1.deptno
=e3.deptno
) AND e1.deptno
=e2.deptno
;
#6.根据emp,dept表找出部门10中既不是经理也不是普通员工,而且工资大于等于2000的员工
SELECT * FROM b_emp WHERE deptno=10 AND job!=‘MANAGER’ AND job!=‘CLERK’ AND sal>=2000;
SELECT * FROM b_emp WHERE deptno=10 AND job NOT IN (‘MANAGER’,‘CLERK’) AND sal>=2000;
#7.根据emp,dept表得到工资大于自己部门平均工资的员工信息
SELECT e1.*
FROM b_emp e1 WHERE sal>(SELECT AVG(sal) FROM b_emp e2 WHERE e1.deptno=e2.deptno);
#8.根据emp,dept得到每个月工资总数最少的那个部门的部门编号,部门名称,部门位置
SELECT d.* FROM b_dept d,
(SELECT deptno,MIN(total) FROM
(SELECT deptno,SUM(sal) total FROM b_emp WHERE deptno IS NOT NULL GROUP BY deptno) a) t
WHERE d.deptno =t.deptno;
ok
SELECT a.total,d.*
FROM
(SELECT deptno,SUM(sal) total FROM b_emp WHERE deptno IS NOT NULL GROUP BY deptno ORDER BY SUM(sal) ASC) a
LEFT JOIN b_dept d ON a.deptno=d.deptno
LIMIT 0,1;