版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37527943/article/details/85050477
导读
1.多表联查
2.多表连接的方式
3.集合运算符
多表联查
语法:
SELECT 字段
FROM 表1,表2,...,表n
WHERE 条件(拼接条件,其它条件)
ORDER BY;
笛卡尔积:
一张表的笛卡尔积是它本身
两张表的笛卡尔积的结果是:行数相乘,列数相加
三张表的笛卡尔积:m*n*k行
多表联查:避免笛卡尔积
注意:
1.执行流程
FROM,笛卡尔积的结果->WHERE,筛选出主外键值相等的->SELECT,筛选出列
->ORDER BY,排序
2.多表查询时,取主外键值相等的记录才是正确的
拼接条件个数:表的个数-1
3.可以给表取别名,不能三心二意,一旦起别名,就只能使用别名
4.在多表联查时,尽量给每一个列都加表前缀
eg1:查询出每个员工的编号,名字,对应的部门名
SELECT s_emp.id,first_name,name
FROM s_emp,s_dept
WHERE dept_id=s_dept.id;
SELECT e.id,e.first_name,d.name
FROM s_emp e,s_dept d
WHERE e.dept_id = d.id;
eg2:查询薪资高于1000的员工的编号,名字,薪资,部门名
SELECT e.id,e.first_name,e.salary,d.name
FROM s_emp e,s_dept d
WHERE e.dept_id = d.id
AND e.salary>1000;
eg3:查询客户的名字,及其对应的销售的名字
SELECT c.name,e.first_name
FROM s_customer c,s_emp e
WHERE c.sales_rep_id=e.id;
eg4:查询每个员工的名字,对应的部门名,对应的区域名
SELECT e.first_name,d.name as dname,r.name as rname
FROM s_emp e,s_dept d,s_region r
WHERE e.dept_id=d.id
AND d.region_id=r.id;
eg5:查询3号区域所有的员工编号,员工名,区域名,并按照员工名升序排序
SELECT e.id,e.first_name,r.name
FROM s_emp e,s_dept d,s_region r
WHERE e.dept_id=d.id AND d.region_id=r.id
AND r.id=3
ORDER BY e.first_name ASC;
多表连接的方式
等价连接,连接条件是=,常用的方式,以上都是
不等价连接,连接条件不是=,
eg:
CREATE TABLE s_salgrade
(
losal number(4),
hisal number(4),
grade char(1)
);
INSERT INTO s_salgrade VALUES(0,999,'D');
INSERT INTO s_salgrade VALUES(1000,1499,'C');
INSERT INTO s_salgrade VALUES(1500,1999,'B');
INSERT INTO s_salgrade VALUES(2000,2500,'A');
COMMIT;
eg6:查询每个员工的id,名字,薪资,薪资等级
SELECT e.id,e.first_name,e.salary,g.grade
FROM s_emp e,s_salgrade g
WHERE e.salary BETWEEN g.losal AND g.hisal;
外连接,基于等价连接的,
左外连接:结果包含,等价连接的结果和左表不匹配的数据
语法:oracle中有特色语法,接近等价连接
特色语法:
SELECT 字段
FROM 表1,表2
WHERE 表1.列=表2.列(+);
注意:WHERE中=左边的表称为左表,=右边的表称为右表
标准语法:
SELECT 字段
FROM 左表 LEFT [OUTER] JOIN 右表
ON 连接条件
WHERE 其它筛选条件;
右外连接:结果包含,等价连接的结果和右表不匹配的数据
右外可以改成左外,只要会一个就可以了
特色语法:
SELECT 字段
FROM 表1,表2
WHERE 表1.列(+)=表2.列;
注意:WHERE中=左边的表称为左表,=右边的表称为右表
标准语法:
SELECT 字段
FROM 左表 RIGHT [OUTER] JOIN 右表
ON 连接条件
WHERE 其它筛选条件;
全外连接(全连接):结果包含,等价连接的结果和左表,右表不匹配的数据
标准语法: 没有特色语法
SELECT 字段
FROM 左表 FULL [OUTER] JOIN 右表
ON 连接条件
WHERE 其它筛选条件;
eg7: 查询"每个"客户的名字,及其对应的销售的名字,左外
SELECT c.name,e.first_name
FROM s_customer c,s_emp e
WHERE c.sales_rep_id=e.id(+);
查询"每个"客户的名字,及其对应的销售的名字,右外
SELECT c.name,e.first_name
FROM s_customer c,s_emp e
WHERE e.id(+)=c.sales_rep_id;
全外测试语句:
SELECT c.name,e.first_name
FROM s_customer c FULL OUTER JOIN s_emp e
ON e.id=c.sales_rep_id;
内连接:等价于等价连接
语法:
SELECT 字段
FROM 左表 [INNER] JOIN 右表
ON 连接条件
WHERE 其它筛选条件;
SELECT c.name,e.first_name
FROM s_customer c INNER JOIN s_emp e
ON e.id=c.sales_rep_id;
自连接:自己跟自己连接
如果外键列引用了自己表的主键列或唯一列,此时可能用到自连接
eg:查询每个员工的名字,及其领导的名字
SELECT e1.first_name,e2.first_name AS manager_name
FROM s_emp e1,s_emp e2
WHERE e1.manager_id=e2.id(+);
eg:查询薪资高于其领导薪资的员工名,员工薪资,对应的领导名,领导薪资
SELECT e1.first_name,e1.salary,e2.first_name AS m_name,
e2.salary AS m_salary
FROM s_emp e1,s_emp e2
WHERE e1.manager_id=e2.id
AND e1.salary>e2.salary;
集合运算符
集合运算符,
rownum:行号(重点)
union:并集
union all:并
intersect:交集
minus:减
UNION:并集,
包含两个结果集全部的结果,重复的只保留一份,
会按照结果集第一列排序升序排序
SELECT id,first_name
FROM s_emp
WHERE id<15;
SELECT id,first_name
FROM s_emp
WHERE id>5;
eg:
SELECT first_name,id
FROM s_emp
WHERE id<15
UNION
SELECT first_name,id
FROM s_emp
WHERE id>5;
UNION ALL:把两个结果集的结果加起来,不会排序,不会去重
eg:
SELECT first_name,id
FROM s_emp
WHERE id<15
UNION ALL
SELECT first_name,id
FROM s_emp
WHERE id>5;
INTERSECT:交集,取两个结果集中都有的结果,会排序,去重
eg:
SELECT first_name,id
FROM s_emp
WHERE id<15
INTERSECT
SELECT first_name,id
FROM s_emp
WHERE id>5;
MINUS:减,第一个结果集减去(第一个和第二个都有的),会去重,排序
eg:
SELECT first_name,id
FROM s_emp
WHERE id<15
MINUS
SELECT first_name,id
FROM s_emp
WHERE id>5;
rownum:
代表结果集中的行号
是一个伪列,并不是真实存在的
可以用来实现分页
注意:结果集中的行号永远从1开始
rownum条件只要不是从1开始,就是没有结果的
执行流程:
FROM->WHERE->SELECT,结果集确定,行号就确定了->ORDER
现有行号,再排序的
SELECT rownum,id,first_name
FROM s_emp
WHERE id>5;
取用户表的前五个用户:
SELECT rownum,id,first_name
FROM s_emp
WHERE rownum<6;
取用户表的第6~10个用户:
SELECT rownum,id,first_name
FROM s_emp
WHERE rownum>5 AND rownum<11; 错误
SELECT rownum,id,first_name
FROM s_emp
WHERE rownum<11
MINUS
SELECT rownum,id,first_name
FROM s_emp
WHERE rownum<6; 正确的