1. 程式人生 > >Java 10---SELECT多表查詢

Java 10---SELECT多表查詢

導讀

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;                    正確的