SQL 多表查詢之 where和INNER JOIN
SQL多表查詢之 where和INNER JOIN【基礎查詢和效率分析】
轉載Michaelwubo最後釋出於2018-07-05 10:40:47閱讀數 18057收藏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會建議在你的環境中使用它。
- INNERJOIN(內連線,或等值連線):獲取兩個表中欄位匹配關係的記錄。
-
LEFTJOIN(左連線):獲取左表所有記錄,即使右表沒有對應匹配的記錄。
- RIGHTJOIN(右連線): 與LEFTJOIN 相反,用於獲取右表所有記錄,即使左表沒有對應匹配的記錄。
注意:
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
資料庫在通過連線兩張或多張表來返回記錄時,都會生成一張中間的臨時表,然後再將這張臨時表返回給使用者。
在使用leftjion時,on和where條件的區別如下:
1、on條件是在生成臨時表時使用的條件,它不管on中的條件是否為真,都會返回左邊表中的記錄。
2、where條件是在臨時表生成好後,再對臨時表進行過濾的條件。這時已經沒有leftjoin的含義(必須返回左邊表的記錄)了,條件不為真的就全部過濾掉。
假設有兩張表:
表1:tab2
id | size |
1 | 10 |
2 | 20 |
3 | 30 |
表2:tab2
size | name |
10 | AAA |
20 | BBB |
20 | CCC |
兩條SQL:
1、select*formtab1leftjointab2on(tab1.size=tab2.size)wheretab2.name=’AAA’
2、select*formtab1leftjointab2on(tab1.size=tab2.sizeandtab2.name=’AAA’)
第一條SQL的過程:
|
第二條SQL的過程:
|
其實以上結果的關鍵原因就是leftjoin,rightjoin,fulljoin的特殊性,不管on上的條件是否為真都會返回left或right表中的記錄,full則具有left和right的特性的並集。而innerjion沒這個特殊性,則條件放在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);