Java 10---SELECT多表查询

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;                    正确的

猜你喜欢

转载自blog.csdn.net/qq_37527943/article/details/85050477