1. 多表(關聯)查詢
多表查詢也稱之為關聯查詢、多表關聯查詢等,主要是指通過多個表的關聯來獲取數據的一種方式。
1.1. 多表映射關系
一對多:A表的一行數據,對應B表中的多條。如:一個部門可以對應多個員工.
多對一:B表中的多條對應A表的一行數據.如:多個員工對應一個部門.
多對多:學生和選修課表----學生和課程對應表。
一對一:人員基本信息和人員信息擴展表。
1.2. 笛卡爾集
笛卡爾集對於我們數據庫的數據查詢結果的影響:
1. 數據冗余。---笛卡爾集並不是我們所需要的數據.
2. 效率問題:導致數量級的增長。100w *100w,====》1w億。如果你在查詢大量數據的時候,不注意這個笛卡爾集的話,會導致你的查詢結果時間非常非常非常長,還會導致數據庫故障。
因此,在實際運行環境下,應避免使用全笛卡爾集。
笛卡爾集產生的條件:
l 省略連接條件
l 連接條件無效
如下示例:
語句一結果3,語句二結果2,
語句三,無論是加無效連接條件,還是不加條件,結果都是2*3=6,這是由於笛卡爾積的問題,所以要使用有效的連接條件;
如何避免笛卡爾集:
在 WHERE 加入有效的連接條件。
這時候就需要學習表關聯的幾種方式了。
1.3. 多表連接的類型
根據連接方式的不同,Oracle的多表關聯的類型分為:
內連接、外連接、自連接。
內連接分為:等值內連接、不等值內連接
外連接分為:左外連接、右外連接、全外連接
自連接是一種特殊的關聯,可以包含內連接和外連接的連接方式。
1.4. 關於sql99-了解
Oracle是關系型數據庫,它遵的規范(sql規范)。
但是,mysql和Oracle有些地方不一樣,原因:各個廠商的實現可能會有差別。
Sql99 是為了 統一規范多個關系型數據庫的通用語法的
1.5. 多表連接的基本語法
Sql99的語法:
Oracle的語法:
sql語句 優化:
加上前綴:效率高!
1.6. 內連接
1.6.1. 等值內連接
等值內連接也稱之為等值連接。
--需求:查詢一下員工信息,並且顯示其部門名稱 SELECT * FROM emp t1,dept t2 WHERE t1.deptno=t2.deptno; --等值內連接,數據庫的私有擴展語法:隱式內連接(mysql,oracle都支持) SELECT * FROM emp t1 INNER JOIN dept t2 ON t1.deptno=t2.deptno; --sql99語法,顯示內連接(所有符合sql99規范的都支持) 注意:INNER 可以省略
1.6.2. 不等值內連接
不等值內連接也稱之為不等值連接。
--分析:要完成這個需求,需要使用到下面兩張表: --需求:查詢員工信息,要求顯示員工的編號、姓名、月薪、工資級別。 SELECT * FROM emp t1,salgrade t2 WHERE t1.sal >=t2.losal AND t1.sal<=t2.hisal; --隱式語法 SELECT * FROM emp INNER JOIN salgrade ON emp.sal >=salgrade.losal AND emp.sal <=salgrade.hisal --sql99
1.6.3. 表的別名
為什么要使用表的別名?
l 使用別名可以簡化查詢。
l 使用表名前綴可以提高執行效率。--SQL性能優化方案
在不同表中具有相同列名的列,可以用表的別名作為前綴來加以區分。
需要注意的是,如果一旦使用了表的別名,則不能再使用表的真名。
1.6.4. 更多表的連接
1.7. 外連接
分為左外連接,右外連接,全外連接(oracle特有 mysql沒有)。
注意:單表查詢與多表查詢的區別:單表查詢只顯示一個表中的數據,而多表查詢一般會顯示多個表中的數據
至於顯示是全部字段還是部分字段,決定於select后面查詢的內容;
就像左外鏈接查詢和只查詢左表的區別:左外鏈接顯示的是兩表內容,而查詢左表值顯示左表內容
1.7.1. 左外連接
--查詢"所有"員工信息,要求顯示員工號,姓名 ,和部門名稱--要求使用左外連接 SELECT * FROM emp t1 LEFT OUTER JOIN dept t2 ON t1.deptno=t2.deptno; --sql99標准語法 SELECT * FROM emp t1,dept t2 WHERE t1.deptno=t2.deptno(+); --oracle私有語法(mysql不支持),+放到右邊是左外,你可以認為(+)是附加補充的意思。 --要求查詢所有的信息的表,我們可以稱之為主表,而補充信息的表,稱之為從表
注意:外連接的outer可以省略(包括左,右,全連接);
1.7.2. 右外連接
---查詢所有部門及其下屬的員工的信息。--右外連接 SELECT * FROM emp t1 RIGHT OUTER JOIN dept t2 ON t1.deptno=t2.deptno; --sql99--右外連接--右邊表(dept)數據全部顯示。 SELECT * FROM emp t1,dept t2 WHERE t1.deptno(+)=t2.deptno;--oracle語法,右外連接
1.7.3. 如何選擇左外和右外
--1.到底是使用左外還是右外,主要是看兩張表的在語句中的位置, --兩張表是有主從關系,一般把主表放在左邊,----一般兩張表的情況下,我們都使用左連接. SELECT t1.*,t2.* FROM dept t1 ,emp t2 WHERE t1.deptno=t2.deptno(+); --2.+到底是放在條件哪邊?左外連接的+放在右邊,右外連接的+放在左邊. ----記憶的方法:(+)放在從表的一方,起到數據附加的作用. 簡單的說:左外連接就是左邊的表的數據全部顯示,右外就是右邊的表的數據全部顯示。
注意:這種(+)的寫法,只能用在Oracle。不能用於mysql!
一定要有主表和從表這個概念,分清那張是主表,哪張是從表。
把你想查詢基礎表當成左表。想把誰全部都查詢出來就當成主表。
到底哪張是主表哪張是從表?最終還看你的需求。
一般我們把主表放在左邊,使用左外連接。
一般情況下,我們就用左連接就行了。
1.7.4. 全外連接
左表和右表的數據全部都顯示,而且不是笛卡爾集。相當於左外+右外的數據。
【示例】
需求:要求將所有員工和所有部門都顯示出來
--全外連接 SELECT * FROM emp t1 LEFT OUTER JOIN dept t2 on t1.deptno=t2.deptno UNION -- union 去重 SELECT * FROM emp t1 RIGHT JOIN dept t2 ON t1.deptno=t2.deptno; SELECT empno, ename ,dname FROM emp LEFT JOIN dept ON emp.deptno= dept.deptno UNION ALL --union all 不去重 SELECT empno, ename ,dname FROM emp right JOIN dept ON emp.deptno= dept.deptno; --sql99 SELECT * FROM emp t1 FULL OUTER JOIN dept t2 ON t1.deptno=t2.deptno; -- full 去重 --sql99語法,Oracle沒有私有擴展的語法。而且,mysql沒有全外(mysql只能使用前兩種方式,沒有第三種方式)
1.8. 自連接
自連接,就是將一張表當成兩張表來查詢。
1.8.1. 示例
自連接的查詢的原理:就是將一張表當成兩張表來使用.
【示例】
1.查詢員工信息,要求同時顯示員工和員工的領導的姓名
2.查詢“所有”員工信息,要求同時顯示員工和員工的領導的姓名
--查詢員工信息,要求同時顯示員工和員工的領導的姓名 SELECT * FROM emp t1,emp t2 WHERE t1.mgr=t2.empno; --查詢“所有”員工信息,要求同時顯示員工和員工的領導的姓名 SELECT * FROM emp t1,emp t2 WHERE t1.mgr=t2.empno(+);
實質:自連接實質上也是一種特殊的多表連接方式,可以使用內連接和外連接的操作.
注意問題:你也要注意笛卡爾集的產生.