SQL的內連接、左連接和右連接


外連接(out join)

外連接分為外左連接(left outer join)和外右連接(right outer join)

注釋:left outer join 與 left join 等價,    一般寫成left join 
           right outer join 與 right join等價,一般寫成right join

左連接,取左邊的表的全部,右邊的表按條件,符合的顯示,不符合則顯示null

舉例:select <select list> from A left join B on A.id=B.id

 

右連接:取右邊的表的全部,左邊的表按條件,符合的顯示,不符合則顯示null

舉例:select <select list> from A right join B on A.id=B.id

 

 

內連接(inner join)

內連接:也稱為等值連接,返回兩張表都滿足條件的部分

注釋:inner join 就等於 join 

SQL INNER JOIN

 

交叉連接(CROSS JOIN)

交叉連接:返回左表中的所有行,左表中的每一行與右表中的所有行組合。交叉聯接也稱作笛卡爾積

首先,先簡單解釋一下笛卡爾積:笛卡爾乘積是指在數學中,兩個集合XY的笛卡尓積(Cartesian product),又稱直積,表示為X × Y,第一個對象是X的成員而第二個對象是Y的所有可能有序對的其中一個成員

舉例:

現在,我們有兩個集合A和B。

A = {0,1}     B = {2,3,4}

集合 A×B 和 B×A的結果集就可以分別表示為以下這種形式:

A×B = {(0,2),(1,2),(0,3),(1,3),(0,4),(1,4)};

B×A = {(2,0),(2,1),(3,0),(3,1),(4,0),(4,1)};

以上A×B和B×A的結果就可以叫做兩個集合相乘的‘笛卡爾積’。

從以上的數據分析我們可以得出以下兩點結論:

1,兩個集合相乘,不滿足交換率,既 A×B ≠ B×A;

2,A集合和B集合相乘,包含了集合A中元素和集合B中元素相結合的所有的可能性。既兩個集合相乘得到的新集合的元素個數是 A集合的元素個數 × B集合的元素個數;

 

交叉連接有兩種,顯式的和隱式的,不帶ON子句,返回的是兩表的乘積,也叫笛卡爾積。
例如:下面的語句1和語句2的結果是相同的。

語句1:隱式的交叉連接,沒有CROSS JOIN。
SELECT O.ID, O.ORDER_NUMBER, C.ID, C.NAME
FROM ORDERS O , CUSTOMERS C
WHERE O.ID=1;

語句2:顯式的交叉連接,使用CROSS JOIN。
SELECT O.ID,O.ORDER_NUMBER,C.ID,
C.NAME
FROM ORDERS O CROSS JOIN CUSTOMERS C
WHERE O.ID=1;
 

 

內連接和where的區別:

數據庫表連接數據行匹配時所遵循的算法就是以上提到的笛卡爾積,表與表之間的連接可以看成是在做乘法運算。

比如現在數據庫中有兩張表,student表和 student_subject表,如下所示:

  

我們執行以下的sql語句,只是純粹的進行表連接。

SELECT * from student JOIN student_subject;
SELECT * from student_subject JOIN student;

看一下執行結果:

  

     表1.0                            表1.1

從執行結果上來看,結果符合我們以上提出的兩點結論(紅線標注部分);

以第一條sql語句為例我們來看一下他的執行流程,

1,from語句把student表 和 student_subject表從數據庫文件加載到內存中。

2,join語句相當於對兩張表做了乘法運算,把student表中的每一行記錄按照順序和student_subject表中記錄依次匹配。

3,匹配完成后,我們得到了一張有 (student中記錄數 × student_subject表中記錄數)條的臨時表。 在內存中形成的臨時表如表1.0所示。我們又把內存中表1.0所示的表稱為‘笛卡爾積表’。  

再看一下sql中主要關鍵字的執行順序:

from  
on  
join  
where  
group by  
having  
select  
distinct  
union  
order by  

 我們看到on是在join和where前面的

       如果兩張表的數據量都比較大的話,先Join會先進行笛卡爾積計算,再使用where篩選,那樣就會占用很大的內存空間這顯然是不合理的。所以,我們在進行表連接查詢的時候一般都會使用JOIN xxx ON xxx的語法,ON語句的執行是在JOIN語句之前的,也就是說兩張表數據行之間進行匹配的時候,會先判斷數據行是否符合ON語句后面的條件,再決定是否JOIN。

  因此,有一個顯而易見的SQL優化的方案是,當兩張表的數據量比較大,又需要連接查詢時,應該使用 FROM table1 JOIN table2 ON xxx的語法,避免使用 FROM table1,table2 WHERE xxx 的語法,因為后者會在內存中先生成一張數據量比較大的笛卡爾積表,增加了內存的開銷。

 

全連接(Full join)

全外連接是在結果中除了顯示滿足連接的條件的行外,還顯示了join兩側表中所有滿足檢索條件的行

 

關鍵字group by 、 Having的 用法

GROUP BY我們可以先從字面上來理解,GROUP表示分組,BY后面寫字段名,就表示根據哪個字段進行分組,如果有用Excel比較多的話,GROUP BY比較類似Excel里面的透視表。
GROUP BY必須得配合聚合函數來用,分組之后你可以計數(COUNT),求和(SUM),求平均數(AVG)等。

常用聚合函數

    • count() 計數
    • sum() 求和
    • avg() 平均數
    • max() 最大值
    • min() 最小值

我們現在有一張dept_emp表共四個字段,分別是emp_no(員工編號),dept_no(部門編號),from_date(起始時間),to_date(結束時間),記錄了員工在某一部門所處時間段,to_date等於9999-01-01的表示目前還在職。 

 

部門人數

我們現在想知道每個部門有多少名在職員工,步驟如下:

  1. 篩選在職員工 where to_date='9999-01-01';
  2. 對部門進行分組group by dept_no
  3. 對員工進行計數 count(emp_no)
完整語句如下:
SELECT dept_no as 部門, count( emp_no) as 人數 FROM dept_emp WHERE to_date = '9999-01-01' GROUP BY dept_no

結果:
 
HAVING

當然提到GROUP BY 我們就不得不提到HAVING,HAVING相當於條件篩選,但它與WHERE篩選不同,HAVING是對於GROUP BY對象進行篩選。
我們舉個例子:
每個部門人數都有了,那如果我們想要進一步知道員工人數大於30000的部門是哪些,這個時候就得用到HAVING了。
語句如下:

SELECT ( SELECT d.dept_name FROM departments d WHERE de.dept_no = d.dept_no ) AS 部門, count( de.emp_no ) AS 人數 FROM dept_emp de WHERE de.to_date = '9999-01-01' GROUP BY de.dept_no HAVING count( de.emp_no ) > 30000 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM