SQL Fundamentals || 多表查询(内连接,外连接(LEFT|RIGHT|FULL OUTER JOIN),自身关联,ON,USING,集合运算UNION)
SQL Fundamentals || Oracle SQL语言
一、多表查询基本语法
- 在进行多表连接查询的时候,由于数据库内部的处理机制,会产生一些“无用”的数据,而这些数据就称为笛卡尔积.
- 多表查询时可以利用等值关联字段消除笛卡尔积
- 多表查询之中,每当增加一个关联表都需要设置消除笛卡尔积的条件
- 分析过程很重要:
- 确定所需要的数据表
- 确定已知的关联字段:
- 按照SQL语句的执行步骤编写:FROM,WHERE,SELECT,ORDER BY
(由于SELECT是在WHERE子句之后执行,所以SELECT子句所定义的别名WHERE不可以直接使用)
(由于SELECT是在ORDER BY子句之前执行,所以SELECT子句所定义的别名ORDER BY可以直接使用)
二、表的连接操作
- 内连接、等值连接、连接、普通连接、自然连接
- 外连接(左外连接,右外连接),外连接可以通过“(+)”符号进行控制。
三、自身关联
自身关联属于一张表自己关联自己的情况,此时依然会产生笛卡尔积
四:SQL:1999语法
交叉连接的:交叉连接会产生笛卡尔积;
自然连接:自然连接可以自动匹配关联字段消除笛卡尔积;
ON子句
USING子句
全外连接:如果要实现全外连接只能够依靠SQL:1999语法。LEFT|RIGHT|FULL OUTER JOIN
五、数据的集合运算
数据的集合操作:UNION、UNION ALL、INTERSECT、MINUS
集合操作时,各个查询语句返回的结构要求一致
开发之中建议使用UNION来代替OR操作
一、多表查询基本语法
1、多表查询的语法:
多表查询就是在一条查询语句中,从多张表里一起取出所需要的数据,如果要想进行多表查询,直接在FROM子句之后跟上多个表即可,此时的语法如下:
SELECT [DISTINCT] * | 列名称 [AS] [列别名] , 列名称 [AS] [列别名] ,... FROM 表名称1 [表别名1] , 表名称2 [表别名2] …. [WHERE 条件(s) ] [ORDER BY 排序的字段1 ASC|DESC ,排序的字段2 ASC | DESC ..]; |
2、笛卡尔积:
在进行多表连接查询的时候,由于数据库内部的处理机制,会产生一些“无用”的数据,而这些数据就称为笛卡尔积。
通过之前的查询可以发现,笛卡尔积返回的56条查询结果正好是 14 * 4(emp表数据量 * dept表数据量)的运算结果,即,同一条数据重复显示了N次。
- 查询emp表中的数据量 —— 14条数据
SELECT COUNT(*) FROM emp ;
- 查询dept表中的数据量 —— 4条数据
SELECT COUNT(*) FROM dept ;
- 现在查询所有的雇员和部门的全部详细信息
SELECT * FROM emp,dept ;
3、消除笛卡尔积:
多表查询会产生笛卡尔积,所以性能较差;
多表查询时可以利用等值关联字段消除笛卡尔积。
SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno ;
SELECT * FROM emp e , dept d WHERE e.deptno=d.deptno;
4、举例:查询每个雇员的编号、姓名、职位、基本工资、部门名称、部门位置信息
分析过程:
- 确定所需要的数据表
- emp表
- dept表
- 确定已知的关联字段:
- 部门和雇员的关联:emp.deptno=dept.depno
- 按照SQL语句的执行步骤编写:FROM,WHERE,SELECT
SELECT emp.empno,emp.ename,emp.job,emp.sal,dept.dname,dept.loc FROM emp,dept WHERE emp.deptno=dept.deptno ; |
5、给表设置别名,查询雇员的编号、姓名、职位、基本工资、部门名称、部门位置
SELECT e.empno,e.ename,e.job,e.sal,d.dname,d.loc FROM emp e,dept d WHERE e.deptno=d.deptno ; |
6、BETWEEN AND查询出每个雇员的编号、姓名、雇佣日期、基本工资、工资等级
SELECT e.empno,e.ename,e.hiredate,e.sal,s.grade FROM emp e,salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal ; |
7、DECODE为了更加清楚的显示出工资等级的信息,现在希望可以按如下格式进行替换显示:
- grade=1:显示为“E等工资”
- grade=2:显示为“D等工资”
- grade=3:显示为“C等工资”
- grade=4:显示为“B等工资”
- grade=5:显示为“A等工资”
SELECT e.empno,e.ename,e.hiredate,e.sal, DECODE(s.grade,1,'E等工资',2,'D等工资',3,'C等工资',4,'B等工资',5,'A等工资') grade FROM emp e,salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal ; |
8、查询出每个雇员的姓名、职位、基本工资、部门名称、工资所在公司的工资等级;
SELECT e.ename,e.job,e.sal,d.dname,s.grade , DECODE(s.grade,1,'E等工资',2,'D等工资',3,'C等工资',4,'B等工资',5,'A等工资') grade FROM emp e,dept d,salgrade s WHERE e.deptno=d.deptno AND e.sal BETWEEN s.losal AND s.hisal ; |
二、表的连接操作
对于数据表的连接操作在数据库之中一共定义了两种:
内连接 等值连接 连接 普通连接 自然连接 |
是最早的一种连接方式, 内连接是从结果表中删除与其他被连接表中没有匹配行的所有元组,所以当匹配条件不满足时内连接可能会丢失信息。 在之前所使用的连接方式都属于内连接,而在WHERE子句之中设置的消除笛卡尔积的条件就采用了等值判断的方式进行的; 举例:现在将emp和dept表联合查询,使用内连接(等值连接) SELECT * FROM emp e,dept d WHERE e.deptno=d.deptno ; |
外连接 |
内连接中只能够显示等值满足的条件,如果不满足的条件则无法显示, 如果现在希望特定表中的数据可以全部显示,就利用外连接, 外连接分为三种: 左外连接(简称:左连接) 右外连接(简称:右连接) 全外连接(简称:全连接) 在Oracle中可以利用其提供的“(+)”进行左外连接或右外连接的实现,使用如下:
使用左外连接, SELECT * FROM emp e,dept d WHERE e.deptno=d.deptno(+) ; 增加右外连接,显示部门40的信息 SELECT * FROM emp e,dept d WHERE e.deptno(+)=d.deptno ; |
三、自身关联
1、举例:
查询出每个雇员的编号、姓名及其上级领导的编号、姓名,
只需要用到一个emp表中的两个字段,将emp表分别别名为e和m
SQL> SELECT ename,empno,mgr FROM emp; ENAME EMPNO MGR ---------- ---------- ---------- SMITH 7369 7902 FORD 7902 7566 SQL> SELECT e.empno eno, e.ename ename,m.empno mno,m.ename mname 2 FROM emp e,emp m 3 WHERE e.mgr=m.empno; ENO ENAME MNO MNAME 7369 SMITH 7902 FORD SELECT e.empno eno ,e.ename ename,m.empno mno,m.ename mname FROM emp e,emp m WHERE e.mgr=m.empno(+) ; |
2、举例:
查询出在1981年雇佣的全部雇员的编号、姓名、雇佣日期(按照年-月-日显示)、工作、领导姓名、雇员月工资、雇员年工资(基本工资+奖金),雇员工资等级、部门编号、部门名称、部门位置,并且要求这些雇员的月基本工资在1500~3500之间,将最后的结果按照年工资的降序排列,如果年工资相等,则按照工作进行排序
步骤一:查询emp表中的信息(全部雇员的编号、姓名、雇佣日期(按照年-月-日显示),月基本工资在1500~3500之间)
SELECT e.empno,e.ename,e.hiredate,e.sal,(e.sal+NVL(e.comm,0))*12 income FROM emp e WHERE TO_CHAR(e.hiredate,'yyyy')='1981' AND e.sal BETWEEN 1500 AND 3500 |
步骤二:emp表使用自身关联,加入领导的信息,使用别名设置emp表的别名为m,使用关联条件e.mgr=m.empno(+) 消除笛卡尔积
SELECT e.empno,e.ename,e.hiredate,e.sal,(e.sal+NVL(e.comm,0))*12 income , m.ename mname FROM emp e ,em m WHERE TO_CHAR(e.hiredate,'yyyy')='1981' AND e.sal BETWEEN 1500 AND 3500 AND e.mgr=m.empno(+) |
步骤三:dept表加入部门信息,使用外连接 e.mgr=m.empno(+),使用关联条件 e.deptno=d.deptno 消除笛卡尔积
SELECT e.empno,e.ename,e.hiredate,e.sal,(e.sal+NVL(e.comm,0))*12 income , m.ename mname ,d.deptno,d.dname,d.loc FROM emp e ,em m , dept d WHERE TO_CHAR(e.hiredate,'yyyy')='1981' AND e.sal BETWEEN 1500 AND 3500 AND e.mgr=m.empno(+) AND e.deptno=d.deptno |
步骤四:salgrade表查询工资等级,使用关联条件 e.sal BETWEEN s.losal AND s.hisal 消除笛卡尔积
SELECT e.empno,e.ename,e.hiredate,e.sal,(e.sal+NVL(e.comm,0))*12 income , m.ename mname , d.deptno,d.dname,d.loc , s.grade, DECODE(s.grade,1,'E等工资',2,'D等工资',3,'C等工资',4,'B等工资',5,'A等工资') 工资等级 FROM emp e , emp m , dept d , salgrade s WHERE TO_CHAR(e.hiredate,'yyyy')='1981' AND e.sal BETWEEN 1500 AND 3500 AND e.mgr=m.empno(+) AND e.deptno=d.deptno AND e.sal BETWEEN s.losal AND s.hisal |
步骤五:进行排序,
由于SELECT是在ORDER BY子句之前执行,所以SELECT子句所定义的别名ORDER BY可以直接使用
SELECT e.empno,e.ename,e.hiredate,e.sal,(e.sal+NVL(e.comm,0))*12 income , m.ename mname , d.deptno,d.dname,d.loc , s.grade, DECODE(s.grade,1,'E等工资',2,'D等工资',3,'C等工资',4,'B等工资',5,'A等工资') 工资等级 FROM emp e , emp m , dept d , salgrade s WHERE TO_CHAR(e.hiredate,'yyyy')='1981' AND e.sal BETWEEN 1500 AND 3500 AND e.mgr=m.empno(+) AND e.deptno=d.deptno AND e.sal BETWEEN s.losal AND s.hisal ORDER BY income DESC , e.job ; |
四:SQL:1999语法
SQL:1999语法
SELECT [DISTINCT] * | 列名称 [AS] [列别名] , 列名称 [AS] [列别名] ,... FROM 表1 表别名1 [CROSS JOIN 表2 表别名2]| [NATURAL JOIN 表2 表别名2]| [JOIN 表2 USING(关联列名称)]| [JOIN 表2 ON(关联条件)]| [LEFT|RIGHT|FULL OUTER JOIN 表2 ON(关联条件)] [WHERE 条件(s)] [ORDER BY 排序的字段1 ASC|DESC ,排序的字段2 ASC | DESC ..]; |
交叉连接(CROSS JOIN) |
作用于两个关系上,并且第一个关系的每个元组与第二个关系的所有元组进行连接,这样的操作形式与笛卡尔积是完全相同的, 交叉连接的语法:
使用交叉连接(CROSS JOIN),产生笛卡尔积 SELECT * FROM emp CROSS JOIN dept ; |
|
使用自然连接(NATION JOIN) |
自然连接(NATURAL JOIN)运算作用于两个关系,最终会通过两个关系产生出一个关系作为结果。 与交叉连接(笛卡尔积)不同的是, 自然连接只考虑那些在两个关系模式中都出现的属性上取值相同的元组对。 自然连接的操作语法:
SELECT * FROM emp NATURAL JOIN dept ; |
|
USING字句 |
通过自然连接可以直接使用关联字段消除掉笛卡尔积, 如果现在的两张表中没有存在这种关联字段的话,就可以通过USING子句完成笛卡尔积的消除, USING子句的语法如下所示:
USING子句,直接使用JOIN进行连接,同时指定关联的列
|
|
on字句 |
在之前编写等值连接时,采用了关联字段进行笛卡尔积的消除,那么用户在SQL:1999语法之中通过ON子句就可以由用户手工设置一个关联条件,ON子句语法:
ON子句,直接编写条件
ON(e.sal BETWEEN s.losal AND s.hisal) ; |
|
外连接 |
在数据的查询操作中数据的外连接一共分为三种形式:左外连接、右外连接、全外连接,而此时连接的语法如下:
使用SQL:1999语法实现左外连接
使用SQL:1999语法实现右外连接
使用SQL:1999语法实现全外连接
FROM emp e FULL OUTER JOIN dept d ON (e.deptno=d.deptno) ; |
五、数据的集合运算
数据的集合操作:UNION、UNION ALL、INTERSECT、MINUS
集合操作时,各个查询语句返回的结构要求一致
开发之中建议使用UNION来代替OR操作
SELECT * FROM emp WHERE job='SAL' OR job='CL'; |
SELECT * FROM emp WHERE job IN ('SAL' ,'CL'); |
SELECT * FROM emp WHERE job='SAL' UNION SELECT * FROM emp WHERE;OR job='CL'; |
集合运算是一种二目运算符,一共包括四种运算符:并、差、交、笛卡尔积
操作集合的语法如下所示:
查询语句 [UNION | UNION ALL | INTERSECT | MINUS] 查询语句 .... |
要实现集合的运算,主要使用四种运算符:
并操作是将多个查询的结果连接到一起,而对于并操作提供了两种操作符:UNION(不显示重复)、UNION ALL(显示重复)。
UNION(并集) (不显示重复) |
返回若干个查询结果的全部内容,但是重复元组不显示;
UNION SELECT * FROM dept WHERE deptno=10 ; |
UNION ALL(并集) (显示重复) |
返回若干个查询结果的全部内容,重复元组也会显示;
UNION ALL SELECT * FROM dept WHERE deptno=10 ; |
MINUS(差集): |
返回若干个查询结果中的不同部分; 使用MINUS执行差集操作
MINUS SELECT * FROM dept WHERE deptno=10 ; |
INTERSECT(交集): |
返回若干个查询结果中的相同部分。 使用INTERSECT执行交集操作
INTERSECT SELECT * FROM dept WHERE deptno=10 ; |
SQL Fundamentals || 多表查询(内连接,外连接(LEFT|RIGHT|FULL OUTER JOIN),自身关联,ON,USING,集合运算UNION)的更多相关文章
- 【SQL】多表查询中的 外连接 ,on,where
先简单粗暴给个结论,多表连结查询中,on比where更早起作用,系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where进行匹配过滤,where后语句为真,则能查询出来,而通过外连接 ...
- mysql数据库中的多表查询(内连接,外连接,子查询)
用两个表(a_table.b_table),关联字段a_table.a_id和b_table.b_id来演示一下MySQL的内连接.外连接( 左(外)连接.右(外)连接.全(外)连接). MySQL版 ...
- 知识点:Oracle+表连接方式(内连接-外连接-自连接)+详解 来自百度文库
Oracle 表之间的连接分为三种: 1. 内连接(自然连接) 2. 外连接 (1)左外连接 (左边的表不加限制) (2)右外连接(右边的表不加限制) (3)全外连接(左右 ...
- sql内连接外连接自然连接
为什么我们要使用内连接和外连接呢?可以从两张或者多张表中找出,我们需要的属性. 这个比较好:http://www.cnblogs.com/youzhangjin/archive/2009/05/22/ ...
- SQL总结 连表查询
连接查询包括合并.内连接.外连接和交叉连接,如果涉及多表查询,了解这些连接的特点很重要. 只有真正了解它们之间的区别,才能正确使用. 1.Union UNION 操作符用于合并两个或多个 SELECT ...
- 数据库SQL的多表查询
数据库 SQL 的多表查询:eg: table1: employees, table2: departments,table3: salary_grades; 一:内连接: 1):等值连接: 把表em ...
- Python进阶----多表查询(内连,左连,右连), 子查询(in,带比较运算符)
Python进阶----多表查询(内连,左连,右连), 子查询(in,带比较运算符) 一丶多表查询 多表连接查询的应用场景: 连接是关系数据库模型的主要特点,也是区别于其他 ...
- SQL的多表查询(笛卡尔积原理)
感谢大佬:https://blog.csdn.net/yang5726685/article/details/53538438 MySQL的多表查询(笛卡尔积原理) 先确定数据要用到哪些表. 将多个表 ...
- 基于ACCESS和ASP的SQL多个表查询与计算统计代码(一)
近期在写几个关于"Project - Subitem - Task"的管理系统,说是系统还是有点夸大了,基本就是一个多表查询调用和insert.update的数据库操作.仅仅是出现 ...
随机推荐
- C#------Aspose.cells使用方法
转载: http://www.cnblogs.com/muer/p/yaxle.html 代码: public ActionResult ImportData(HttpPostedFileBase f ...
- Go并发编程(四)
并发基础 多进程 多线程 基于回调的非阻塞/异步IO 协程 协程 与传统的系统级线程和进程相比,协程的最大优势在于其“轻量级”,可以轻松创建上百万个而不会导致系统资源衰竭, ...
- (转)base64编码是怎么工作的?
按:在PHP中级班的课堂上,有位同学问这样一个问题:“我在用 base64_encode 对用户名进行编码时,会出来等号,是不是可以去掉?”跟我来看完这篇文章,答案即揭晓. 1: 为什么需要base6 ...
- fork(), waitpid()
NAME fork - create a child process SYNOPSIS #include <unistd.h> pid_t fork(void); RETURN VALUE ...
- PHP 使用 MongoDB
PHP 想要往 MongoDB 里增删查改数据,需要先安装 mongodb 或 mongo 扩展模块,一般两个都装上: cd /usr/local/src/ wget https://pecl.php ...
- Zabbix的自定义键值和自动发现功能监控Oracle数据库的表空间
前面介绍了利用Orabbix监控了,参考zabbix通过Orabbix监控oracle数据库,这里我们原先的模板中进行了修改,使用自动发现功能实现监控tablespace的使用情况. 1. 在被监控的 ...
- PHP curl get post通用类
<?php /** * @author:xiaojiang * curl 通用方法 ..get /post 传送数据 */ class process{ const GET = 0; const ...
- 《转》python学习(11)-表达式和语句
转自 http://www.cnblogs.com/BeginMan/p/3164600.html 一.Python语句 if语句.else语句.elif语句.条件表达式.while语句.for语句. ...
- 基于VLAN的二三层转发
[章节内容]1 MAC地址2 冲突域和广播域3 集线器.交换机.路由器 3.1 集线器 3.2 网桥和交换机 3.3 路由器4 VLAN 4.1 VLAN帧格式 4.1.1 ...
- Win8交互UX——键盘交互
设计用户可以通过硬件键盘.屏幕键盘或触摸键盘交互的 Windows 应用商店应用. 本主题介绍键盘交互的设计注意事项.有关实现键盘交互的信息,请参阅响应键盘输入. 键盘交互 键盘输入是 Windows ...