sql連線查詢中on篩選與where篩選的區別

2021-09-20 16:47:26 字數 2729 閱讀 3254

sql查詢這個東西, 要說它簡單, 可以很簡單, 通常情況下只需使用增刪查改配合程式語言的邏輯表達能力,就能實現所有功能。 但是增刪查改並不能代表sql語句的所有, 完整的sql功能會另人望而生畏。 就拿比普通增刪查改稍微複雜乙個層次的連線查詢來說, 盲目使用, 也會出現意料之外的危險結果,導致程式出現莫名其妙的bug。 

在連線查詢語法中,另人迷惑首當其衝的就要屬on篩選和where篩選的區別了,  在我們編寫查詢的時候, 篩選條件的放置不管是在on後面還是where後面, 查出來的結果總是一樣的, 既然如此,那為什麼還要多此一舉的讓sql查詢支援兩種篩選器呢?  事實上, 這兩種篩選器是存在差別的,只是如果不深挖不容易發現而已。

sql中的連線查詢分為3種, cross join,inner join,和outer join ,  在 cross join和inner join中,篩選條件放在on後面還是where後面是沒區別的,極端一點,在編寫這兩種連線查詢的時候,只用on不使用where也沒有什麼問題。因此,on篩選和where篩選的差別只是針對outer join,也就是平時最常使用的left join和right join。

來看乙個示例,有兩張資料表,結構和資料如圖所示

表main

表ext

可以把這兩張表看作是用來存放使用者資訊的, main放置主要資訊,ext表放置附加資訊,兩張表的關係是1對1的,以id字元作為對應關係鍵。現在我們需要將位址不為杭州的所有使用者資訊篩選出來,結果中需要包含main表和ext表的所有字段資料。

select * from main left join  exton main.id = ext.id  and  address <> '杭州'

閉上眼睛, 請用大腦人肉執行一下這段sql, 想象一下是什麼結果。

當把address <> '杭州'這個篩選條件放在on之後,查詢得到的結果似乎跟我們預料中的不同,從結果中能看出,這個篩選條件好像只過濾掉了ext表中對應的記錄,而main表中的記錄並沒有被過濾掉,也就是上圖中標記為紅色的那條記錄。outer join相對於inner join的乙個主要特性就是以一側的表為基礎,但是在這裡以左表為基這一點卻可以無視篩選條件,這未免也太霸道了一些。

把查詢語句稍微改動一下,將位址的篩選條件從on轉移至where

select * from main left join  ext on main.id = ext.id  where address <> '杭州'

結果就如我們預期的那樣了

造成這種結果上的差異要從outer join查詢的邏輯查詢的各個階段說起。總的來說,outer join 的執行過程分為4步

1、先對兩個表執行交叉連線(笛卡爾積)

2、應用on篩選器

3、新增外部行

4、應用where篩選器

就拿上面不使用where篩選器的sql來說,執行的整個詳細過程如下

第一步,對兩個表執行交叉連線,結果如下,這一步會產生36條記錄(此圖顯示不全)

第二步,應用on篩選器。篩選器中有兩個條件,main.id = ext.id  and address<> '杭州',符合要求的記錄如下

這似乎正是我們期望中查詢的結果,然而在接下來的步驟中這個結果會被打亂

第三步,新增外部行。outer join有乙個特點就是以一側的表為基,假如另一側的表沒有符合on篩選條件的記錄,則以null替代。在這次的查詢中,這一步的作用就是將那條原本應該被過濾掉的記錄給新增了回來

是不是不種畫蛇添足的感覺, 結果就成了這樣

第四步,應用where篩選器

在這條問題sql中,因為沒有where篩選器,所以上一步的結果就是最終的結果了。

而對於那條位址篩選在where條件中的sql,這一步便起到了作用,將所有位址不屬於杭州的記錄篩選了出來

通過上面的講解,已經能反應出在outer join中的篩選條件在on中和where中的區別,開發人員如能詳細了解之中差別,能規避很多在編寫sql過程**現的莫名其妙的錯誤。

sshpp

sql連線查詢中on篩選與where篩選的區別

sql查詢這個東西,要說它簡單,可以很簡單,通常情況下只需使用增刪查改配合程式語言的邏輯表達能力,就能實現所有功能。但是增刪查改並不能代表sql語句的所有,完整的sql功能會另人望而生畏。就拿比普通增刪查改稍微複雜乙個層次的連線查詢來說,盲目使用,也會出現意料之外的危險結果,導致程式出現莫名其妙的b...

sql中的連線查詢

create table 產品 產品編號 char 9 not null,產品名稱 varchar 20 not null go create table 產品銷量 產品編號 char 9 not null,銷量 int go insert into 產品 values 001 顯示器 insert...

SQL中的連線查詢

1 整體說明 1 所謂連線,按字面理解就是將表拼在一起,當做一張表使用 2 內連線 顧名思義,也就是兩張表的重疊部分 即青色部分 都滿足才行 3 左外連線 也就是將左邊的表也連線起來,結果就是所有左邊的資料加上滿足重疊部分條件的右邊部分 4 右外連線 右邊所有表的資料,加上滿足重疊部分條件的左邊的資...