国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

關(guān)于Left join,你可能不知道這些......

運(yùn)維 數(shù)據(jù)庫運(yùn)維
join 是 SQL查詢中很常見的一種操作,具體來講有join,left join, right join,full join等很多形式。具體的原理如下圖所示。但其中最常見的還是使用left join 。

join 是 SQL查詢中很常見的一種操作,具體來講有join,left join, right join,full join等很多形式。具體的原理如下圖所示。但其中最常見的還是使用left join 。

本文代碼在mysql和hive中均測試通過,代碼本身難度和長度都不大,我準(zhǔn)備了測試數(shù)據(jù)的mysql和hive代碼,如果覺得有必要,你可以在后臺回復(fù)“left”獲取,方便自己修改和練習(xí)。

left join 通俗的解釋:以左表為主表,返回左表的所有行,如果右表中沒有匹配,則依然會有左表的記錄,右表字段用null填充。看起來非常好理解,但實(shí)際操作的過程中可能會有一些很容易被忽略的點(diǎn)。

一、left join 之后的記錄有幾條

關(guān)于這一點(diǎn),是要理解left join執(zhí)行的條件。在A join B的時候,我們在on語句里指定兩表關(guān)聯(lián)的鍵。只要是符合鍵值相等的,都會出現(xiàn)在結(jié)果中。這里面有一對一,一對多,多對多等幾種情況。我們用例子來說明。

1、一對一

這種情況最好理解。t_name表,有id,name(用戶名稱),sex(性別),dt(注冊日期)等字段。t_age表。有id,age(年齡),province(省份),dt(更新日期)等字段。表中包含的信息如下:

現(xiàn)在我們進(jìn)行t_name(左表,別名a)和t_age(右表,別名b)的left join 操作,關(guān)聯(lián)鍵為id。a表有6條記錄,b表有3條記錄,且關(guān)鍵的鍵是唯一的,因此最終結(jié)果以a表為準(zhǔn)有6條記錄,b表有3條關(guān)聯(lián)不上,相應(yīng)的記錄中,b表所有的字段都為空。

2、一對多

這回我們用t_age作為左表,關(guān)聯(lián)條件為dt。重點(diǎn)看dt為20190905的記錄。由于右表有3條20190905,這三條在關(guān)聯(lián)的時候都滿足關(guān)聯(lián)條件,因此最終的結(jié)果會有3條記錄是20190905。

這回為準(zhǔn)的表是t_age表,但顯然結(jié)果并不是原本的3條記錄,而是7條:20190905 3條,20190906 4條。如果你不太理解,可以繼續(xù)往下看。

3、多對多

上面例子中,20190906的記錄最終有4條,同樣是因?yàn)闈M足了關(guān)聯(lián)條件,是一種2對2的情況。這里我們還是回到t_name表做主表的情況,用dt來關(guān)聯(lián)。可以預(yù)見,與2中相比,這次結(jié)果中會多一行20190907的,而b表相應(yīng)的字段依然為空。

2和3中我們看到了一對多和多對多的情況,其實(shí)前者是后者的特例。我們只是很簡要的把兩個表關(guān)聯(lián)之后所有的字段都列出來了,但實(shí)際中可能需要做一些統(tǒng)計,聚合等。這里提醒大家在寫關(guān)聯(lián)條件之前,最好思考一下最終的結(jié)果是什么樣的,最終可能有幾行,會不會在計數(shù)的時候多統(tǒng)計,哪些行可能會存在空值,哪些字段可能會存在空值等。不要因?yàn)橄氘?dāng)然而犯了錯誤。這里算是拋磚引玉,感興趣的同學(xué)可以看看這篇博客,進(jìn)一步學(xué)習(xí),

https://www.cnblogs.com/qdhxhz/p/10897315.html

二、left join 的執(zhí)行原理

接下來我們進(jìn)一步看一下連接條件寫在on里和寫在where里的區(qū)別。在這之前,我們可以看看left join的具體執(zhí)行邏輯。我參考了網(wǎng)上以為大神的博客:

https://developer.aliyun.com/article/718897,總結(jié)如下

mysql采用嵌套循環(huán)的方式處理left join。

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í)行邏輯可以描述為:   

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

如果代碼看不懂,直接看結(jié)論就好:

  1.   如果想對右表進(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ǔ)齊右表,但是此時我們的P2對右表行進(jìn)行了限制,NULL若不滿足P2(NULL一般都不會滿足限制條件,除非IS NULL這種),則不會加入最終的結(jié)果中,導(dǎo)致結(jié)果缺失。

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

我們再來看看實(shí)例,返回來研究這段話可能更好理解一些。

1、只有1個on條件

這里可以直接看第一部分中的例子。最終會輸出以左表為準(zhǔn),右表匹配不上補(bǔ)null的結(jié)果,但可能會有多對多的情況。

2、有2個on條件

上圖是在關(guān)聯(lián)條件中增加了b.age=24之后的輸出結(jié)果。由于對b表進(jìn)行了限制,滿足條件的只有一個,但是由于沒有where條件,因此依然要以左表為準(zhǔn),又因?yàn)槭且粚σ唬暂敵鲞€是左表的記錄數(shù)。更極端的,我們可以“清空”b表。

以上兩種情況,在b表中都沒有符合條件的結(jié)果,因此在以左表為準(zhǔn)的基礎(chǔ)上,右邊的所有字段都為空。

3、有where的情況

將b.age=24寫到where里,發(fā)現(xiàn)結(jié)果中只有這一行,打破了“left join”以左表為主的限制。同樣再來看下后兩種情況寫到where里會發(fā)生什么:

沒錯,結(jié)果全部是為空的。因?yàn)閣here 在 on 后面執(zhí)行,而on生成的結(jié)果里沒有滿足條件的記錄!

這里給出兩個結(jié)論:

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

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

4、有is null 或者有 is not null的情況

當(dāng)條件寫在on中:

當(dāng)條件寫在where 中:

直觀的我們理解,WHERE … IS NULL 子句將從匹配階段后的數(shù)據(jù)中過濾掉不滿足匹配條件的數(shù)據(jù)行。對于條件寫在on中的情況,又可以說,is null是否定匹配條件,is not null是肯定匹配條件。對于條件寫在where中的,其實(shí)相比之下更容易理解,要看已有的where條件產(chǎn)生的結(jié)果是什么。讀者可以從上面的例子中思考一下。

三、看兩個實(shí)際案例

經(jīng)過上面的討論,我們來看兩個案例,進(jìn)一步理解和思考一下left join 的用法。

1、案例1

這個案例來自于一篇網(wǎng)絡(luò)博客,前文有提到。鏈接:

https://developer.aliyun.com/article/718897

大家可以先思考一下怎么寫再到原文看答案。事實(shí)上,每個需求都很容易有兩種寫法,區(qū)別就在于條件是寫在where中還是寫在on中。判斷的原則就是我們需要保證結(jié)果中數(shù)據(jù)不缺失也不多余。需求1的條件需要寫在on中(保證結(jié)果不缺失),需求2的條件需要寫在where中(保證結(jié)果不多余)。

2、案例2

假設(shè)現(xiàn)在有一個用戶活躍表t_active,記錄了每天活躍的uid和相應(yīng)的活躍日期。現(xiàn)在想要看距離某一天日期差為0天,1天,2天,3天…活躍的用戶在當(dāng)天還有多少活躍(也就是一個留存的概念)。期望得到的如下表所示:

對于表中數(shù)據(jù),我們可以這樣理解。距離2019-09-29 0天(也就是2019-09-29)的活躍人數(shù)為100,2019-09-29當(dāng)天活躍的還剩100,距離2019-09-29 1天(也就是2019-09-28)的活躍人數(shù)為80,2019-09-29當(dāng)天還剩60。以此類推。

對于這個需求,我們可以使用left join進(jìn)行自關(guān)聯(lián),用之前活躍的天作為左表,最終期望計算的天作為右表,計算日期差,并進(jìn)行左右表分別計數(shù)。初步的SQL如下:(數(shù)據(jù)是自己編的)

在往下看之前請確認(rèn)你理解了需求目標(biāo),并先思考下,以上的寫法有問題嗎?能否得到上面期望的結(jié)果?

原始數(shù)據(jù)和這段SQL運(yùn)行的結(jié)果如下:

運(yùn)行結(jié)果中出現(xiàn)了dt和datediff為null的情況,你能想象的到這是為什么嗎?而且當(dāng)dt不為null的時候,最后兩列的數(shù)據(jù)是相同的,顯然和我們的預(yù)期不符。這是什么原因呢?我們來逐步看一下。

首先,我們使用left join 的方式應(yīng)該是沒有問題的,我們先看看不加任何計算的,select * 的結(jié)果是啥。

可以看到,這相當(dāng)于是前文提到的不加where 條件的一對一關(guān)聯(lián),結(jié)果會以左表為準(zhǔn),關(guān)聯(lián)不上的用null補(bǔ)齊。值得注意的是,關(guān)聯(lián)不上的日期是null值,而null值在參與datediff的計算時,結(jié)果會是null。到這里你是不是明白一點(diǎn)了。由于null值參與計算,導(dǎo)致最終datediff 有null值,并且計數(shù)的時候,由于null值存在,最終用日期差作為維度的時候,導(dǎo)致左表和右表的數(shù)量是一樣的。如下面代碼所示:

從上面的結(jié)果我們可以推演出最開始的SQL運(yùn)行結(jié)果。例如,datediff=5的時候,共兩條記錄,左表右表的count(distinct uid)都為2。datediff為null的時候,左表結(jié)果為7,右表為0,其他的以此類推,和前面的結(jié)果是一樣的。這樣我們就知道了,沒有達(dá)到預(yù)期的根源在于存在空的日期。那么怎么解決這個問題呢,顯然就是把空日期填補(bǔ)上就可以了。可以使用case when 當(dāng)右表日期關(guān)聯(lián)不上的時候,用相應(yīng)日期補(bǔ)足。代碼如下:

可以看到最終得到了想要的結(jié)果,以最后一行為例,它表示,距離2019-09-29 5天的那天(也就是2019-09-24)活躍的人數(shù)有5個,那些人在2019-09-29仍然活躍的有2人,你可以看一下明細(xì)數(shù)據(jù)核對一下。其余的以此類推。我們使用case when 把日期寫死了,這個是建立在我們知道是哪天的基礎(chǔ)上的。實(shí)際中可能是一個變量,但一定也是一個固定的值,需要具體情況具體分析。

四、總結(jié)

本文我們學(xué)習(xí)了left join的原理和實(shí)踐中可能會遇到的問題。包括關(guān)聯(lián)時結(jié)果中的記錄數(shù),關(guān)聯(lián)條件寫在on和where中的區(qū)別,where語句中存在is null的時候如何理解,最后用實(shí)例幫助大家進(jìn)行理解。在此過程中參考了網(wǎng)上的一些博客,大家可以在閱讀本文的基礎(chǔ)上進(jìn)行查閱。希望對你有所幫助!后臺回復(fù)“left”,可以獲取本文測試所用的數(shù)據(jù)集合代碼。 

 

責(zé)任編輯:龐桂玉 來源: 數(shù)據(jù)庫開發(fā)
相關(guān)推薦

2019-11-20 10:25:06

sudoLinux

2018-05-10 11:50:13

Docker容器冷知識

2022-02-23 14:18:02

macOSMac時間機(jī)器

2012-11-23 10:57:44

Shell

2021-01-05 11:22:58

Python字符串代碼

2020-01-29 19:40:36

Python美好,一直在身邊Line

2015-08-13 09:03:14

調(diào)試技巧

2020-10-28 08:06:09

Vue3框架數(shù)據(jù)

2015-07-13 08:49:54

2023-02-27 09:20:24

絕對定位CSS

2023-01-29 09:46:47

Dialog彈窗模態(tài)

2014-11-21 10:25:18

Java

2019-11-25 14:05:47

Python裝飾器數(shù)據(jù)

2014-12-08 10:39:15

2011-11-30 13:34:13

2010-05-19 09:01:00

2021-07-12 07:59:06

安全 HTML 屬性

2015-02-02 14:12:03

云桌面

2022-05-05 12:02:45

SCSS函數(shù)開發(fā)

2015-05-14 15:59:33

DockerLinux容器管理工具
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

久久xxx视频| 91小视频在线观看| 中文字幕精品一区久久久久| 日韩av电影免费| 国产传媒久久文化传媒| 91久久夜色精品国产网站| av成人免费看| 日韩欧美亚洲一区二区| 免费h片在线观看| 成人国产精品视频| 欧美日韩一区二区三区在线观看免| 美女主播精品视频一二三四| 亚洲人成网在线播放| 欧美精品日韩少妇| 亚洲综合色在线| 99热在线这里只有精品| 久久久精品五月天| 亚洲综合中文字幕在线| 精品欧美午夜寂寞影院| 久久久999成人| 成年美女黄网站色大片不卡| 欧美日韩国产首页| 性色视频在线| 国产香蕉精品视频一区二区三区| 免费成人午夜视频| 亚洲在线日韩| 欧美丰满少妇xxxxx| 极品美乳网红视频免费在线观看| 亚洲激情一区| 神马亚洲视频| av高清久久久| 国内福利写真片视频在线| 在线不卡中文字幕| 农村妇女一区二区| 欧美精品国产一区| 不卡电影一区二区三区| 91精品国产一区二区三区动漫| 成人线上视频| 欧美成人精品1314www| 日本а中文在线天堂| 日韩欧美精品在线| 影音先锋在线亚洲| 视频一区二区国产| 九九九九久久久久| 国产精品久久久亚洲一区| 91黄色精品| 在线电影一区二区| 成人福利视频在线观看| 久久亚洲在线| 99re视频| 欧美亚洲自偷自偷| 五月天色一区| 国产一区二区成人久久免费影院| 2021狠狠干| av影院午夜一区| 国产精彩免费视频| 亚洲欧美日韩一区二区 | 91极品视觉盛宴| jyzzz在线观看视频| 欧美精品一级二级| 无遮挡在线观看| 色综合伊人色综合网| av一级久久| 97成人精品区在线播放| 亚洲精品国产偷自在线观看| 美日韩免费视频| 国产精品综合av一区二区国产馆| 国产美女三级视频| 精品高清美女精品国产区| 99免在线观看免费视频高清| 欧美www视频| 精品69视频一区二区三区| 91av免费观看91av精品在线| 欧美在线免费| 伊人久久青草| 国产精品美女一区二区三区| 欧美日韩国产中文字幕在线| 亚洲精品在线观| 日韩区欧美区| 99久久伊人精品影院| 国产美女主播视频一区| 蜜臀av免费观看| 91黄色小视频| 九九九伊在线综合永久| 国产精品香蕉在线观看| 久久精品国产久精国产爱| 综合网插菊花| 欧美α欧美αv大片| 久久这里只有精品一区二区| 国产精品一国产精品最新章节| 国产成人av一区| 在线国产视频观看| 色系列之999| 欧美高清一区| 日韩一区二区三区四区| 国产精品有限公司| 波多野结衣中文字幕一区二区三区| 一级视频在线观看视频在线啦啦 | 黄色精品在线看| а√天堂中文资源在线bt| 26uuu日韩精品一区二区| 在线亚洲国产精品网站| 色国产在线视频| 日韩一区二区高清| 激情综合网五月| 国产在线视频在线| 在线观看不卡一区| 美女视频一区| 青青草成人激情在线| 亚洲蜜桃精久久久久久久| 欧美三级网站| 5566中文字幕一区二区| 国产午夜精品久久久久久免费视| 国产日产一区二区| 国产成人在线亚洲欧美| 奇米777欧美一区二区| 黄页视频在线免费观看| 伊人亚洲福利一区二区三区| 一区在线免费| 97在线观看| 日韩中文字幕国产| 人人爽香蕉精品| 国产69久久| 国产精品旅馆在线| 国产午夜精品在线观看| 东京一区二区| 日本一区免费在线观看| 欧美性生交大片免网| 免费一区二区三区视频导航| 国产深夜男女无套内射| 日韩精品中文字幕一区| 国产一区亚洲| 欧美写真视频一区| 97精品国产97久久久久久| 99久久99久久综合| 97成人资源| 中文字幕免费在线不卡| 欧美浪妇xxxx高跟鞋交| 99久久夜色精品国产亚洲1000部| a优女a优女片| 久久久久国色av免费观看性色| www.色综合.com| 欧美舌奴丨vk视频| 精品国产三级a∨在线| 精品动漫一区二区三区在线观看| 国内视频精品| 国产精品久久久久久久龚玥菲 | 无人视频在线观看免费| 久久免费视频在线| 久久日一线二线三线suv| 成人啊v在线| 国产美女主播在线| 亚洲欧美国产va在线影院| 免费成人美女在线观看| 制服丝袜中文字幕在线| 日本不卡高清视频一区| 7777精品伊人久久久大香线蕉经典版下载| 欧美aⅴ99久久黑人专区| 四虎在线视频| 亚洲自拍av在线| 91久久国产综合久久| 欧美三级网页| eeuss影院www在线观看| 国产乱码精品一区二区三区不卡| 欧美色倩网站大全免费| 激情久久中文字幕| 日本在线视频观看| 日本不卡一区| 成人爽a毛片| 国产高清自产拍av在线| 操你啦视频在线| 亚洲成av人影片在线观看| 5566中文字幕一区二区| 精品国产一区二区三区久久久狼| 欧美精品videosex牲欧美| 欧美一级淫片videoshd| 日韩成人在线资源| 欧美人与动牲交xxxxbbbb| 番号在线播放| 欧美激情 亚洲a∨综合| 亚洲精品免费在线| 欧美夫妻性生活视频| 亚洲欧美综合色| 日韩影片中文字幕| 成人影院av| 天堂av一区| 精品色999| 国产剧情一区二区| 一本色道久久综合亚洲精品不| 日韩二区三区| 久久国产精品久久精品国产| 精品福利在线导航| 久久这里只有精品首页| 精品国产一级毛片| 成人看片免费| 啊啊啊一区二区| 国产视频观看一区| 欧美精品一区二区三| 国产视频一区二区在线观看| 91精品一区二区三区综合|