SQL 多表查詢之 where和INNER JOIN


SQL多表查詢之 where和INNER JOIN【基礎查詢和效率分析】

https://blog.csdn.net/u013372487/article/details/52622491?locationNum=1

https://blog.csdn.net/qingtanlang/article/details/2133816

http://www.cnblogs.com/drake-guo/p/6101531.html

https://blog.csdn.net/huyr_123/article/details/61616547

 

在多表查詢中,一些SQL開發人員更喜歡使用WHERE來做join,比如:

SELECT a.ID, b.Name, b.Date FROM Customers a, Sales b WHERE a.ID = b.ID;

缺點:在上面語句中,實際上是創建了兩張表的笛卡爾積,所有可能的組合都會被創建出來。在笛卡爾連接中,在上面的例子中,如果有1000顧客和1000條銷售記錄,這個查詢會先產生1000000個結果,然后通過正確的 ID過濾出1000條記錄。 這是一種低效利用數據庫資源,數據庫多做100倍的工作。 在大型數據庫中,笛卡爾連接是一個大問題,對兩個大表的笛卡爾積會創建數10億或萬億的記錄。

為了避免創建笛卡爾積,應該使用INNER JOIN :

SELECT a.ID, b.Name, b.Date FROM Customers a INNER JOIN Sales b ON a.ID = b.ID;

 

優點:如上面語句,使用inner join 這樣數據庫就只產生等於ID 的1000條目標結果。增加了查詢效率。

有些數據庫系統會識別出 WHERE連接並自動轉換為 INNER JOIN。在這些數據庫系統中,WHERE 連接與INNER JOIN 就沒有性能差異。但是, INNER JOIN 是所有數據庫都能識別的,因此DBA會建議在你的環境中使用它。

  1.  
    INNER  JOIN(內連接,或等值連接):獲取兩個表中字段匹配關系的記錄。
  2.  
    LEFT JOIN(左連接):獲取左表所有記錄,即使右表沒有對應匹配的記錄。
  3.  
    RIGHT JOIN(右連接): 與 LEFT JOIN 相反,用於獲取右表所有記錄,即使左表沒有對應匹配的記錄。

 

 

注意: 
1、INNER JOIN 等同於 JOIN; 
2、示意圖: 
這里寫圖片描述這里寫圖片描述這里寫圖片描述

這里寫圖片描述

 

 

我在練習MySQL操作語句時,使用一條完全沒有錯誤的語句:

update students set name='drake' where name='chuan';

 

卻報了如下錯誤:

Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column To disable safe mode, toggle the option in Preferences -> SQL Queries and reconnect.
簡單翻譯一下:
你正在使用 安全更新模式(safe upate mode)並且你在嘗試 update 一個表時 沒有用帶有鍵的列 作為where條件,在首選項中切換選項。

 

初學者在修改一個值時可能會用以下語句:

update t set col='new_value' 

 

而這正是很多人常犯的錯誤。因為他沒有限定條件,會將表中所有的記錄都修改一遍。

為了防止這種錯誤出現,我們可以開啟安全更新模式(safe update mode):

 

set [global] SQL_SAFE_UPDATES = 1;

 

 

在update操作中:當where條件中列(column)沒有索引可用且無limit限制時會拒絕更新。where條件為常量且無limit限制時會拒絕更新。

在delete操作中: 當①where條件為常量,②或where條件為空,③或where條件中 列(column)沒有索引可用且無limit限制時拒絕刪除。

 

需要注意的是:

update操作中,where可以為常量  ,where條件中列(column)可以沒有索引。但是需要有limit限制。

然而delete要嚴格一些:where不能為常量,且where條件中列(column)不能沒有索引!

 

1 .WHERE子句中使用的連接語句,在數據庫語言中,被稱為隱性連接。INNER JOIN……ON子句產生的連接稱為顯性連接。(其他JOIN參數也是顯性連接)WHERE 和INNER JOIN產生的連接關系,沒有本質區別,結果也一樣。但是!隱性連接隨着數據庫語言的規范和發展,已經逐漸被淘汰,比較新的數據庫語言基本上已經拋棄了隱性連接,全部采用顯性連接了。

 

2 .無論怎么連接,都可以用join子句,但是連接同一個表的時候,注意要定義別名,否則產生錯誤!

a> left join:理解為“有效連接”,兩張表中都有的數據才會顯示left join:理解為“有左顯示”,比如on a.field=b.field,則顯示a表中存在的全部數據及a//b中都有的數據,A中有、B沒有的數據以null顯示

b> right join:理解為“有右顯示”,比如on a.field=b.field,則顯示B表中存在的全部數據及a//b中都有的數據,B中有、A沒有的數據以null顯示

c> full join:理解為“全連接”,兩張表中所有數據都顯示,實際就是inner +(left-inner)+(right-inner)

3 .join可以分主次表   外聯接有三種類型:完全外聯,左聯,右聯.
完全外聯包含兩張表的所有記錄.
左聯是以左邊的表為主,右邊的為輔,右聯則相反

 

語法格式:
    其實 INNER JOIN ……ON的語法格式可以概括為:
    FROM (((表1 INNER JOIN 表2 ON 表1.字段號=表2.字段號) INNER JOIN 表3 ON 表1.字段號=表3.字段號) INNER JOIN 表4 ON Member.字段號=表4.字段號) INNER JOIN 表X ON Member.字段號=表X.字段號
    您只要套用該格式就可以了。
    
    現成格式范例:
    雖然我說得已經比較明白了,但為照顧初學者,我還是以本會員注冊系統為例,提供一些現成的語法格式范例,大家只要修改其中的數據表名稱和字段名稱即可。
    
    連接兩個數據表的用法:
    FROM Member INNER JOIN MemberSort ON Member.MemberSort=MemberSort.MemberSort
    語法格式可以概括為:
    FROM 表1 INNER JOIN 表2 ON 表1.字段號=表2.字段號
    
    連接三個數據表的用法:
    FROM (Member INNER JOIN MemberSort ON Member.MemberSort=MemberSort.MemberSort) INNER JOIN MemberLevel ON Member.MemberLevel=MemberLevel.MemberLevel 
    語法格式可以概括為:
    FROM (表1 INNER JOIN 表2 ON 表1.字段號=表2.字段號) INNER JOIN 表3 ON 表1.字段號=表3.字段號
    
    連接四個數據表的用法:
    FROM ((Member INNER JOIN MemberSort ON Member.MemberSort=MemberSort.MemberSort) INNER JOIN MemberLevel ON Member.MemberLevel=MemberLevel.MemberLevel) INNER JOIN MemberIdentity ON Member.MemberIdentity=MemberIdentity.MemberIdentity
    語法格式可以概括為:
    FROM ((表1 INNER JOIN 表2 ON 表1.字段號=表2.字段號) INNER JOIN 表3 ON 表1.字段號=表3.字段號) INNER JOIN 表4 ON Member.字段號=表4.字段號
    
    連接五個數據表的用法:
    FROM (((Member INNER JOIN MemberSort ON Member.MemberSort=MemberSort.MemberSort) INNER JOIN MemberLevel ON Member.MemberLevel=MemberLevel.MemberLevel) INNER JOIN MemberIdentity ON Member.MemberIdentity=MemberIdentity.MemberIdentity) INNER JOIN Wedlock ON Member.Wedlock=Wedlock.Wedlock
    語法格式可以概括為:
    FROM (((表1 INNER JOIN 表2 ON 表1.字段號=表2.字段號) INNER JOIN 表3 ON 表1.字段號=表3.字段號) INNER JOIN 表4 ON Member.字段號=表4.字段號) INNER JOIN 表5 ON Member.字段號=表5.字段號

 

 

 

left join :左連接,返回左表中所有的記錄以及右表中連接字段相等的記錄。

right join :右連接,返回右表中所有的記錄以及左表中連接字段相等的記錄。

inner join: 內連接,又叫等值連接,只返回兩個表中連接字段相等的行。

full join:外連接,返回兩個表中的行:left join + right join。

cross join:結果是笛卡爾積,就是第一個表的行數乘以第二個表的行數。

關鍵字: on

數據庫在通過連接兩張或多張表來返回記錄時,都會生成一張中間的臨時表,然后再將這張臨時表返回給用戶。

在使用left jion時,on和where條件的區別如下:

1、 on條件是在生成臨時表時使用的條件,它不管on中的條件是否為真,都會返回左邊表中的記錄。

2、where條件是在臨時表生成好后,再對臨時表進行過濾的條件。這時已經沒有left join的含義(必須返回左邊表的記錄)了,條件不為真的就全部過濾掉。

假設有兩張表:

表1:tab2

id size
1 10
2 20
3 30

表2:tab2

size name
10 AAA
20 BBB
20 CCC

兩條SQL:
1、select * form tab1 left join tab2 on (tab1.size = tab2.size) where tab2.name=’AAA’
2、select * form tab1 left join tab2 on (tab1.size = tab2.size and tab2.name=’AAA’)

第一條SQL的過程:

 

1、中間表
on條件:
tab1.size = tab2.size
tab1.id tab1.size tab2.size tab2.name
1 10 10 AAA
2 20 20 BBB
2 20 20 CCC
3 30 (null) (null)

 

   
2、再對中間表過濾
where 條件:
tab2.name=’AAA’
tab1.id tab1.size tab2.size tab2.name
1 10 10 AAA

 

   

 

第二條SQL的過程:

 

1、中間表
on條件:
tab1.size = tab2.size and tab2.name=’AAA’
(條件不為真也會返回左表中的記錄)
tab1.id tab1.size tab2.size tab2.name
1 10 10 AAA
2 20 (null) (null)
3 30 (null) (null)

 

 

其實以上結果的關鍵原因就是left join,right join,full join的特殊性,不管on上的條件是否為真都會返回left或right表中的記錄,full則具有left和right的特性的並集。 而inner jion沒這個特殊性,則條件放在on中和where中,返回的結果集是相同的。

連接查詢是將兩個或多個的表按某個條件連接起來,從中選取需要的數據,連接查詢是同時查詢兩個或兩個以上的表的使用的。當不同的表中存在相同意義的字段時,可以通過該字段來連接這幾個表。

 

     1.內連接查詢

            內連接查詢是一種最常用的連接查詢。內查詢可以查詢兩個或兩個以上的表。舉例說明兩個表的連接查詢。當該字段的值相等時,就查詢出該記錄。

      舉個栗子~

       SELECT  num,name,employee.d_id,sex,d_name,function

               FROM employee ,department

                WHERE employee.d_id=department.d_id;

 

      2.外連接查詢

            基本語法:

                 SELECT 屬性名列表

                                FROM 表名1  LEFT | RIGHT JOIN 表名2

                                ON 表名1.屬性1=表名2.屬性2;

 

 

  • 左連接查詢

                   進行左連接查詢時,可以查出表1的表中所有記錄,而表2所指的表中,只能查詢出匹配的記錄

 

  • 右連接查詢

                  進行右連接查詢時,可以查出表2的表中所有記錄,而表1所指的表中,只能查詢出匹配的記錄

     3.復合·條件查詢

                  在連接查詢時,也可以增加其他的限制條件,使查詢結果更加准確。

 

 

子查詢

       子查詢是將一個查詢語句嵌套在另外一個查詢語句中,內層查詢語句的查詢結果,可以為外層查詢語句提供查詢條件。

          舉個栗子~IN

          SELECT   *   FROM   employee

                       WHERE  d_id   IN

                         (SELECT   d_id    FROM   department);

          還 舉個栗子~比較運算符

          SELECT  id ,name, score FROM computer_stu

                    WHERE  score>=

                           (SELECT score FROM scholarship

                              WHERE level=1);

           還 舉個栗子~EXISTS(表示存在,使用EXISTS關鍵字時,內層查詢語句不反悔查詢的記錄,而是返回一個真假值)

          SELECT  *   FROM employee

                        WHERE EXISTS

                       ( SELECT d_name FROM department

                                    WHERE d_id =1003);

            還 舉個栗子~ANY(表示滿足其中任一條件)

                如查詢獲得任意一個獎學金的最低分,即只要獲得獎學金都滿足條件

          SELECT * FROM computer_stu

                 WHERE score >=ANY

                         ( SELECT score FROM scholarship);

               最后一個栗子~ALL(表示滿足所有條件)

                如查詢獲得最高獎學金的記錄

           SELECT * FROM computer_stu

                  WHERE score >=ALL

                         ( SELECT score FROM scholarship);


免責聲明!

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



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