SQL JOIN語法,以及JOIN where 和and區別,還有where和join效率問題。


語法

join 用於根據兩個或多個表中的列之間的關系,從這些表中查詢數據。

Join 和 Key

有時為了得到完整的結果,我們需要從兩個或更多的表中獲取結果。我們就需要執行 join。

數據庫中的表可通過鍵將彼此聯系起來。主鍵(Primary Key)是一個列,在這個列中的每一行的值都是唯一的。在表中,每個主鍵的值都是唯一的。這樣做的目的是在不重復每個表中的所有數據的情況下,把表間的數據交叉捆綁在一起。

請看 "Persons" 表:

Id_P LastName FirstName Address City
1 Adams John Oxford Street London
2 Bush George Fifth Avenue New York
3 Carter Thomas Changan Street Beijing

請注意,"Id_P" 列是 Persons 表中的的主鍵。這意味着沒有兩行能夠擁有相同的 Id_P。即使兩個人的姓名完全相同,Id_P 也可以區分他們。

接下來請看 "Orders" 表:

Id_O OrderNo Id_P
1 77895 3
2 44678 3
3 22456 1
4 24562 1
5 34764 65

請注意,"Id_O" 列是 Orders 表中的的主鍵,同時,"Orders" 表中的 "Id_P" 列用於引用 "Persons" 表中的人,而無需使用他們的確切姓名。

請留意,"Id_P" 列把上面的兩個表聯系了起來。

引用兩個表

我們可以通過引用兩個表的方式,從兩個表中獲取數據:

誰訂購了產品,並且他們訂購了什么產品?

SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons, Orders
WHERE Persons.Id_P = Orders.Id_P 

結果集:

LastName FirstName OrderNo
Adams John 22456
Adams John 24562
Carter Thomas 77895
Carter Thomas 44678

SQL JOIN - 使用 Join

除了上面的方法,我們也可以使用關鍵詞 JOIN 來從兩個表中獲取數據。

如果我們希望列出所有人的定購,可以使用下面的 SELECT 語句:

SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons
INNER JOIN Orders
ON Persons.Id_P = Orders.Id_P
ORDER BY Persons.LastName

結果集:

LastName FirstName OrderNo
Adams John 22456
Adams John 24562
Carter Thomas 77895
Carter Thomas 44678

不同的 SQL JOIN

除了我們在上面的例子中使用的 INNER JOIN(內連接),我們還可以使用其他幾種連接。

下面列出了您可以使用的 JOIN 類型,以及它們之間的差異。

  • JOIN: 如果表中有至少一個匹配,則返回行
  • LEFT JOIN: 即使右表中沒有匹配,也從左表返回所有的行
  • RIGHT JOIN: 即使左表中沒有匹配,也從右表返回所有的行
  • FULL JOIN: 只要其中一個表中存在匹配,就返回行

 

之前例子是inner join 現在展示 left join 和 full join

 

left join

 

"Persons" 表:

Id_P LastName FirstName Address City
1 Adams John Oxford Street London
2 Bush George Fifth Avenue New York
3 Carter Thomas Changan Street Beijing

"Orders" 表:

Id_O OrderNo Id_P
1 77895 3
2 44678 3
3 22456 1
4 24562 1
5 34764 65

左連接(LEFT JOIN)實例

現在,我們希望列出所有的人,以及他們的定購 - 如果有的話。

您可以使用下面的 SELECT 語句:

SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons
LEFT JOIN Orders
ON Persons.Id_P=Orders.Id_P
ORDER BY Persons.LastName

結果集:

LastName FirstName OrderNo
Adams John 22456
Adams John 24562
Carter Thomas 77895
Carter Thomas 44678
Bush George  

LEFT JOIN 關鍵字會從左表 (Persons) 那里返回所有的行,即使在右表 (Orders) 中沒有匹配的行。

 

full join

原始的表 (用在例子中的):

"Persons" 表:

Id_P LastName FirstName Address City
1 Adams John Oxford Street London
2 Bush George Fifth Avenue New York
3 Carter Thomas Changan Street Beijing

"Orders" 表:

Id_O OrderNo Id_P
1 77895 3
2 44678 3
3 22456 1
4 24562 1
5 34764 65

全連接(FULL JOIN)實例

現在,我們希望列出所有的人,以及他們的定單,以及所有的定單,以及定購它們的人。

您可以使用下面的 SELECT 語句:

SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons
FULL JOIN Orders
ON Persons.Id_P=Orders.Id_P
ORDER BY Persons.LastName

結果集:

LastName FirstName OrderNo
Adams John 22456
Adams John 24562
Carter Thomas 77895
Carter Thomas 44678
Bush George  
    34764

FULL JOIN 關鍵字會從左表 (Persons) 和右表 (Orders) 那里返回所有的行。如果 "Persons" 中的行在表 "Orders" 中沒有匹配,或者如果 "Orders" 中的行在表 "Persons" 中沒有匹配,這些行同樣會列出。

 

join 中的 where 和 and 區別

 

在使用left join時,on and和on where條件的區別如下:  
1、on條件是在生成臨時表時使用的條件,它不管on中的條件是否為真,都會返回左邊表中的記錄。  
2、where條件是在臨時表生成好后,再對臨時表進行過濾的條件。這時已經沒有left join的含義(必須返回左邊表的記錄)了,條件不為真的就全部過濾掉,on后的條件用來生成左右表關聯的臨時表,where后的條件對臨時表中的記錄進行過濾。

 
           
表結構
SQL> create table A (id int, type int);
SQL> select * from A;
        ID       TYPE
---------- ----------
         1          1
         2          1
         3          2
 
SQL> create table B(id int ,class int);
SQL> select * from B;
 
        ID      CLASS
---------- ----------
         1          1
         2          2
不使用條件
SQL> select * from A left join B on A.id = b.id; ID TYPE ID CLASS ---------- ---------- ---------- ---------- 1 1 1 1 2 1 2 2 3 2
使用條件where
SQL> select * from A left join B on A.id = B.id where A.type = 1; ID TYPE ID CLASS ---------- ---------- ---------- ---------- 1 1 1 1 2 1 2 2

根據上面那段話的解釋,where字句是在生成臨時表以后再進行過濾的,也就是可以理解為就是一個左連接:select * from A left join B on A.id = B.id,然后加上where A.type = 1對臨時表進行過濾,除掉A.type不為1的數據。

 

使用and
SQL> select * from A left join B on A.id = B.id and A.type = 1; ID TYPE ID CLASS ---------- ---------- ---------- ---------- 1 1 1 1 2 1 2 2 3 2

因為左連接不管on and語句是否為真都必須返回左表所有的記錄,所以and A.type=1;沒有起到任何作用。

 

SQL> select * from A left join B on A.id = B.id and B.class = 1;
 
        ID       TYPE         ID      CLASS
---------- ---------- ---------- ----------
         1          1          1          1
         3          2
         2          1

根據上面那段話的解釋:on條件是在生成臨時表時使用的條件,它不管on中的條件是否為真,都會返回左邊表中的記錄。顯然左連接再加上新的條件:B.class = 1篩選掉第二行記錄,結果正確。

 

SQL> select * from A left join B on A.id = B.id where B.class = 1;
 
        ID       TYPE         ID      CLASS
---------- ---------- ---------- ----------
         1          1          1          1

where是生成臨時表以后再進行過濾,對左右表都進行篩選。如果是and,先不管過濾規則,先把左邊表數據全部返回,然戶過濾規則只對右表產生過濾。

 

 

再來看看內連接inner join  on and和 on where的區別:

在使用inner join時,不管是對左表還是右表進行篩選,on and和on where都會對生成的臨時表左右兩邊同時進行過濾。

表結構
SQL> select * from A; ID TYPE ---------- ---------- 1 2 2 1 3 2 SQL> select * from B; ID CLASS ---------- ---------- 1 1 2 2
inner join 的特性就是只返回有匹配的
SQL> select * from A inner join B on A.id = B.id; ID TYPE ID CLASS ---------- ---------- ---------- ---------- 1 2 1 1 2 1 2 2
SQL> select * from A inner join B on A.id = B.id where A.type = 1;
 
        ID       TYPE         ID      CLASS
---------- ---------- ---------- ----------
         2          1          2          2
SQL> select * from A inner join B on A.id = B.id and B.class = 1;
 
        ID       TYPE         ID      CLASS
---------- ---------- ---------- ----------
         1          2          1          1
SQL> select * from A inner join B on A.id = B.id where B.class = 1;
 
        ID       TYPE         ID      CLASS
---------- ---------- ---------- ----------
         1          2          1          1

發現會對左右兩邊同時過濾。

 

個人使用join和單純使用where關聯表查詢

個人測試兩個oracle語句

select r.role from user_role ur,Shiro_Role r,shiro_user su where r.id = ur.role_id and ur.user_id = su.id and su.username='cheng' 
select r.role from Shiro_Role r inner join user_role ur on ur.role_id = r.id inner join shiro_user su on su.id = ur.user_id and su.username='cheng';

不使用join第一次查詢為0.329  重復查詢后為0.042到0.026

使用join第一次查詢為0.042  重復后為0.042到0.005

 


免責聲明!

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



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