最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解決Mysql的left join無效及使用的注意事項(xiàng)說明

 更新時(shí)間:2021年07月01日 10:05:00   作者:栗子木  
這篇文章主要介紹了解決Mysql的left join無效及使用的注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Mysql的left join無效及使用

今天寫sql發(fā)現(xiàn)使用left join 沒有把左邊表的數(shù)據(jù)全部查詢出來,讓我郁悶了一會,后來仔細(xì)研究了一會才知道自己犯了個(gè)常識性的錯(cuò)誤(我是菜鳥)

這是原sql

這樣的查詢并不能將tb_line這張表的數(shù)據(jù)都查詢出來,好尷尬...

后面我才知道原來當(dāng)我們進(jìn)行多表查詢,在執(zhí)行到where之前,會先形成一個(gè)臨時(shí)表

而on就是臨時(shí)表中的條件篩選,使用left join則不管條件是否為真,都會查詢出左邊表的數(shù)據(jù),條件為假的,則顯示為null

where則是在臨時(shí)表生成之后的過濾條件

在第一張圖中,我將tb_vehicle這張表的過濾條件放在where之中,那left join所產(chǎn)生條件為假的數(shù)據(jù),則會在where 的 v.del_flag='0'中被過濾掉(因?yàn)闂l件為假的數(shù)據(jù),del_flag都為空)

所以我看似使用了left join ,實(shí)際上這樣寫與使用inner join的結(jié)果是一樣的

正確sql如下:

在臨時(shí)表中就做好條件篩選,這樣就能夠得到左邊表的數(shù)據(jù)

總結(jié):

使用left join 并需要做條件查詢的時(shí)候,需要仔細(xì)斟酌改條件篩選放在on后面還是where后面

Mysql left join 避坑指南

現(xiàn)象

left join在我們使用mysql查詢的過程中可謂非常常見,比如博客里一篇文章有多少條評論、商城里一個(gè)貨物有多少評論、一條評論有多少個(gè)贊等等。但是由于對join、on、where等關(guān)鍵字的不熟悉,有時(shí)候會導(dǎo)致查詢結(jié)果與預(yù)期不符,所以今天我就來總結(jié)一下,一起避坑。

這里我先給出一個(gè)場景,并拋出兩個(gè)問題,如果你都能答對那這篇文章就不用看了。

假設(shè)有一個(gè)班級管理應(yīng)用,有一個(gè)表classes,存了所有的班級;有一個(gè)表students,存了所有的學(xué)生,具體數(shù)據(jù)如下:

SELECT * FROM classes;

SELECT * FROM students;

那么現(xiàn)在有兩個(gè)需求:

找出每個(gè)班級的名稱及其對應(yīng)的女同學(xué)數(shù)量

找出一班的同學(xué)總數(shù)

對于需求1,大多數(shù)人不假思索就能想出如下兩種sql寫法,請問哪種是對的?

SELECT c.name, count(s.name) as num 
    FROM classes c left join students s 
    on s.class_id = c.id 
    and s.gender = 'F'
    group by c.name

或者

SELECT c.name, count(s.name) as num 
    FROM classes c left join students s 
    on s.class_id = c.id 
    where s.gender = 'F'
    group by c.name

對于需求2,大多數(shù)人也可以不假思索的想出如下兩種sql寫法,請問哪種是對的?

SELECT c.name, count(s.name) as num 
    FROM classes c left join students s 
    on s.class_id = c.id 
    where c.name = '一班' 
    group by c.name

或者

SELECT c.name, count(s.name) as num 
    FROM classes c left join students s 
    on s.class_id = c.id 
    and c.name = '一班' 
    group by c.name

請不要繼續(xù)往下翻 ??!先給出你自己的答案,正確答案就在下面。

~

~

~

答案是兩個(gè)需求都是第一條語句是正確的,要搞清楚這個(gè)問題,就得明白mysql對于left join的執(zhí)行原理,下節(jié)進(jìn)行展開。

根源

mysql 對于left join的采用類似嵌套循環(huán)的方式來進(jìn)行從處理,以下面的語句為例:

SELECT * FROM LT LEFT JOIN RT ON P1(LT,RT)) WHERE P2(LT,RT)

其中P1是on過濾條件,缺失則認(rèn)為是TRUE,P2是where過濾條件,缺失也認(rèn)為是TRUE,該語句的執(zhí)行邏輯可以描述為:

FOR each row lt in LT {// 遍歷左表的每一行
  BOOL b = FALSE;
  FOR each row rt in RT such that P1(lt, rt) {// 遍歷右表每一行,找到滿足join條件的行
    IF P2(lt, rt) {//滿足 where 過濾條件
      t:=lt||rt;//合并行,輸出該行
    }
    b=TRUE;// lt在RT中有對應(yīng)的行
  }
  IF (!b) { // 遍歷完RT,發(fā)現(xiàn)lt在RT中沒有有對應(yīng)的行,則嘗試用null補(bǔ)一行
    IF P2(lt,NULL) {// 補(bǔ)上null后滿足 where 過濾條件
      t:=lt||NULL; // 輸出lt和null補(bǔ)上的行
    }         
  }
}

當(dāng)然,實(shí)際情況中MySQL會使用buffer的方式進(jìn)行優(yōu)化,減少行比較次數(shù),不過這不影響關(guān)鍵的執(zhí)行流程,不在本文討論范圍之內(nèi)。

從這個(gè)偽代碼中,我們可以看出兩點(diǎn):

如果想對右表進(jìn)行限制,則一定要在on條件中進(jìn)行,若在where中進(jìn)行則可能導(dǎo)致數(shù)據(jù)缺失,導(dǎo)致左表在右表中無匹配行的行在最終結(jié)果中不出現(xiàn),違背了我們對left join的理解。因?yàn)閷ψ蟊頍o右表匹配行的行而言,遍歷右表后b=FALSE,所以會嘗試用NULL補(bǔ)齊右表,但是此時(shí)我們的P2對右表行進(jìn)行了限制,NULL若不滿足P2(NULL一般都不會滿足限制條件,除非IS NULL這種),則不會加入最終的結(jié)果中,導(dǎo)致結(jié)果缺失。

如果沒有where條件,無論on條件對左表進(jìn)行怎樣的限制,左表的每一行都至少會有一行的合成結(jié)果,對左表行而言,若右表若沒有對應(yīng)的行,則右表遍歷結(jié)束后b=FALSE,會用一行NULL來生成數(shù)據(jù),而這個(gè)數(shù)據(jù)是多余的。所以對左表進(jìn)行過濾必須用where。

下面展開兩個(gè)需求的錯(cuò)誤語句的執(zhí)行結(jié)果和錯(cuò)誤原因:

需求1

需求2

需求1由于在where條件中對右表限制,導(dǎo)致數(shù)據(jù)缺失(四班應(yīng)該有個(gè)為0的結(jié)果)

需求2由于在on條件中對左表限制,導(dǎo)致數(shù)據(jù)多余(其他班的結(jié)果也出來了,還是錯(cuò)的)

總結(jié)

通過上面的問題現(xiàn)象和分析,可以得出了結(jié)論:在left join語句中,左表過濾必須放where條件中,右表過濾必須放on條件中,這樣結(jié)果才能不多不少,剛剛好。

SQL 看似簡單,其實(shí)也有很多細(xì)節(jié)原理在里面,一個(gè)小小的混淆就會造成結(jié)果與預(yù)期不符,所以平時(shí)要注意這些細(xì)節(jié)原理,避免關(guān)鍵時(shí)候出錯(cuò)。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • mysql高效查詢left join和group by(加索引)

    mysql高效查詢left join和group by(加索引)

    這篇文章主要給大家介紹了關(guān)于mysql高效查詢left join和group by,這個(gè)的前提是加了索引,以及如何在MySQL高效的join3個(gè)表 的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • Windows下MySQL詳細(xì)安裝過程及基本使用

    Windows下MySQL詳細(xì)安裝過程及基本使用

    本文詳細(xì)講解了Windows下MySQL安裝過程及基本使用方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2021-12-12
  • MySQL SQL語句優(yōu)化的10條建議

    MySQL SQL語句優(yōu)化的10條建議

    這篇文章主要介紹了MySQL中SQL語句優(yōu)化需要注意的10點(diǎn),,特別是大型高并發(fā)網(wǎng)站,需要的朋友可以參考下
    2014-03-03
  • win11系統(tǒng)下mysql8.4更改數(shù)據(jù)目錄問題解決

    win11系統(tǒng)下mysql8.4更改數(shù)據(jù)目錄問題解決

    更改數(shù)據(jù)庫目錄是指修改MySQL數(shù)據(jù)庫的存儲路徑,本文主要介紹了win11系統(tǒng)下mysql8.4更改數(shù)據(jù)目錄問題解決,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • MySQL避免索引失效的方法示例

    MySQL避免索引失效的方法示例

    索引是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),本文主要介紹了MySQL避免索引失效的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • Mysql優(yōu)化order by語句的方法詳解

    Mysql優(yōu)化order by語句的方法詳解

    本篇文章我們將了解ORDER BY語句的優(yōu)化,在文中給大家提到了mysql中的兩種排序方式,需要的朋友參考下吧
    2018-08-08
  • MySQL8.0.28安裝教程詳細(xì)圖解(windows?64位)

    MySQL8.0.28安裝教程詳細(xì)圖解(windows?64位)

    如果電腦上已經(jīng)有MySQL數(shù)據(jù)庫再進(jìn)行重做往往會遇到問題,下面這篇文章主要給大家介紹了關(guān)于windows?64位系統(tǒng)下MySQL8.0.28安裝教程的詳細(xì)教程,文章通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • 簡單講解MySQL中的多源復(fù)制

    簡單講解MySQL中的多源復(fù)制

    這篇文章主要介紹了簡單講解MySQL中的多源復(fù)制,多源復(fù)制功能自從5.7.2版本以后被加入MySQL,需要的朋友可以參考下
    2015-04-04
  • MySQL和Oracle批量插入SQL的通用寫法示例

    MySQL和Oracle批量插入SQL的通用寫法示例

    當(dāng)我們要往數(shù)據(jù)庫中批量保存多條數(shù)據(jù)得時(shí)候,分不同數(shù)據(jù)庫,有不同得插入方式,這篇文章主要給大家介紹了關(guān)于MySQL和Oracle批量插入SQL的通用寫法的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • MySQL事務(wù)的隔離性是如何實(shí)現(xiàn)的

    MySQL事務(wù)的隔離性是如何實(shí)現(xiàn)的

    最近做了一些分布式事務(wù)的項(xiàng)目,對事務(wù)的隔離性有了更深的認(rèn)識,后續(xù)寫文章聊分布式事務(wù)。今天就復(fù)盤一下單機(jī)事務(wù)的隔離性是如何實(shí)現(xiàn)的?感興趣的可以了解一下-
    2021-09-09

最新評論

天长市| 康定县| 铜梁县| 吴忠市| 大荔县| 株洲市| 湘西| 景德镇市| 耒阳市| 临西县| 汨罗市| 馆陶县| 安龙县| 洞头县| 兴安县| 清涧县| 民权县| 惠来县| 张家港市| 延庆县| 双流县| 渭南市| 彭泽县| 北京市| 平乡县| 南和县| 奈曼旗| 汾西县| 湖北省| 清河县| 崇信县| 大渡口区| 洪泽县| 德昌县| 汉源县| 万载县| 榆树市| 新河县| 和平县| 东方市| 遂川县|