數(shù)據(jù)產(chǎn)品經(jīng)理養(yǎng)成記(四):SQL多張表查詢

上一節(jié)講了SQL簡單查詢,包括SQL語句的分類、基本查詢語句(select)、條件語句、運(yùn)算符等。本節(jié)講一下多表查詢。

舉個(gè)工作中的實(shí)際例子,假設(shè)你在做一款貸款產(chǎn)品,這里有兩張表:用戶表(userinfo)、借款還款表(loanapp)。你想查詢所有用戶的借款總筆數(shù)、借款總金額,就需要以用戶作為關(guān)聯(lián)條件,從三張表里面查找相應(yīng)的數(shù)據(jù)進(jìn)行分析。具體如何實(shí)現(xiàn)?看完下面的內(nèi)容你就能輕松解決這個(gè)問題。

1.表的加法

表的加法是指按行,將表合并在一起,通過關(guān)鍵字union實(shí)現(xiàn)。現(xiàn)在,這里有兩張格式一樣的表,你想把兩張表的數(shù)據(jù)合并起來,該如何操作?

先寫語句再解釋,如下:

select 學(xué)生姓名,學(xué)生編號(hào) --注釋:選擇course1表的兩列數(shù)據(jù)

from 表1

union--注釋:合并

select 學(xué)生姓名,學(xué)生編號(hào) --注釋:選擇course1表的兩列數(shù)據(jù)

from 表2;

運(yùn)行結(jié)果如下:

注意

表1 中有兩行數(shù)據(jù),表2 中有三行數(shù)據(jù),加起來是五行數(shù)據(jù),但是運(yùn)行出來的結(jié)果只有四行數(shù)據(jù)。這是因?yàn)殛P(guān)鍵字【union】會(huì)把表里面重復(fù)的數(shù)據(jù)去重。如果你想保存重復(fù)的行,將【union】改為【union all】即可。

2.表的聯(lián)結(jié)

之前介紹過,關(guān)系數(shù)據(jù)庫中,表和表之間是通過關(guān)系列關(guān)聯(lián)起來的(哪里都要靠這種關(guān)鍵節(jié)點(diǎn),數(shù)據(jù)庫中是,生活中也是這樣,有關(guān)系好辦事。。。)

有了關(guān)系列后,就可以把不同的表聯(lián)結(jié)起來,常見的聯(lián)結(jié)方式有以下幾種:

交叉聯(lián)結(jié)、內(nèi)連接、做鏈接、右聯(lián)結(jié)、全聯(lián)結(jié),我們逐一介紹。

交叉聯(lián)結(jié)(cross join)

又稱為笛卡爾積,作用是將一個(gè)表中的每一行,和另一個(gè)表中的每一行合并在一起。交叉聯(lián)結(jié)后的總行數(shù),是兩張表的行數(shù)的乘機(jī),舉個(gè)例子:

兩個(gè)表交叉聯(lián)結(jié)后的結(jié)果如下:

可以看到,聯(lián)結(jié)后的展示的內(nèi)容,是將兩個(gè)表的內(nèi)容拼起來。表的行數(shù)是兩張表的行數(shù)的乘機(jī):1*2=2.如果第一張表有5行,第二張表有3行,那么兩張表交叉聯(lián)結(jié)后的行數(shù)為:5*3=15.

說明:

交叉聯(lián)結(jié)在實(shí)際業(yè)務(wù)中用的比較少,因?yàn)榻徊媛?lián)結(jié)產(chǎn)生的數(shù)據(jù)太多了,需要耗費(fèi)很多設(shè)備、時(shí)間成本計(jì)算。而且,交叉聯(lián)結(jié)會(huì)產(chǎn)生很多無意義的數(shù)據(jù)。但是,交叉聯(lián)結(jié)是我們接下來要說的幾種聯(lián)結(jié)方式的基礎(chǔ),因此還是有必要了解清楚。

內(nèi)聯(lián)結(jié)(inner join)

作用是選取出同時(shí)存在于兩張表中的數(shù)據(jù),選取后按照交叉聯(lián)結(jié)的方式合并展示出來。

舉個(gè)例子,現(xiàn)在有兩張表,如下:一張學(xué)生信息表,一張學(xué)生成績表,現(xiàn)在你想查出某個(gè)學(xué)生的信息和成績,如何用inner join實(shí)現(xiàn)?

這里先寫語句:

select學(xué)生信息表.學(xué)號(hào),學(xué)生信息表.姓名,學(xué)生成績表.學(xué)號(hào),學(xué)生成績表.課程,學(xué)生成績表.成績--選擇要拼接的列,為了方便區(qū)別這個(gè)列是哪張表的,需在列名前邊加表名

from學(xué)生信息表inner join學(xué)生成績表--選擇拼接的表

on學(xué)生信息表.學(xué)號(hào) = 學(xué)生成績表.學(xué)號(hào);--選擇以哪個(gè)列作為拼接條件

上面兩張表的名稱太長,不管在書寫還是在閱讀上都不方便,能不能給它們起一個(gè)臨時(shí)名稱,以方便書寫?這里可以用關(guān)鍵字as來實(shí)現(xiàn),寫法如下;

select a.學(xué)號(hào),a.姓名,b.學(xué)號(hào),b.課程,b.成績--選擇要拼接的列,為了方便區(qū)別這個(gè)列是哪張表的,需在列名前邊加表名

from學(xué)生信息表as a inner join學(xué)生成績表as b--選擇拼接的表

on a.學(xué)號(hào) = b.學(xué)號(hào);--選擇以哪個(gè)列作為拼接條件

通過以上語句,運(yùn)行處的結(jié)果如下:

說名

內(nèi)聯(lián)結(jié)的SQL 語句運(yùn)行順序如下:

- 將兩個(gè)表里面【學(xué)號(hào)】相同的列的數(shù)據(jù)都取出來。

- 將兩個(gè)表里面取出的數(shù)據(jù)合并,使用交叉聯(lián)結(jié)的方式合并。

- 將一個(gè)表中的所有行與另個(gè)表中所有合并在一起。

左聯(lián)結(jié)

左聯(lián)結(jié)是將左側(cè)表作為主表,并指定主表的某一列為【關(guān)聯(lián)列】。運(yùn)行時(shí),主表的數(shù)據(jù)全部讀出來;右邊表的數(shù)據(jù)按照【關(guān)聯(lián)列】進(jìn)行選取,與【關(guān)聯(lián)列】相同的數(shù)據(jù)會(huì)被選取,不同的數(shù)據(jù)不會(huì)被選取。選取之后,兩個(gè)表的數(shù)據(jù)按照交叉聯(lián)結(jié)的方式合并展示。

舉個(gè)例子,,現(xiàn)在有兩張表,如下:一張學(xué)生信息表,一張學(xué)生成績表,現(xiàn)在通過左聯(lián)結(jié)將以下兩張表合并后的結(jié)果會(huì)是怎樣?

先公布語句寫法:

select a.學(xué)號(hào),a.姓名,b.學(xué)號(hào),b.課程,b.成績

from學(xué)生信息表as a left join 學(xué)生成績表as b

on a.學(xué)號(hào) =b.學(xué)號(hào);

可以發(fā)現(xiàn)語句和寫法和inner join類似。通過以上語句,運(yùn)行處的結(jié)果如下:

因?yàn)閷W(xué)號(hào)0002在右邊的表里沒有對(duì)應(yīng)的行,所以合并后,對(duì)應(yīng)的位置顯示空值。如果你想刪除掉有空值的行,可以通過where字句增加一個(gè)篩選條件,如下:

selecta.學(xué)號(hào),a.姓名,b.學(xué)號(hào),b.課程,b.成績f

rom學(xué)生信息表asaleftjoin學(xué)生成績表asb

ona.學(xué)號(hào) = b.學(xué)號(hào)

whereb.學(xué)號(hào) =null;

右聯(lián)結(jié)

右聯(lián)結(jié)是將右側(cè)表作為主表,并指定主表的某一列為【關(guān)聯(lián)列】。運(yùn)行時(shí),主表的數(shù)據(jù)全部讀出來;左邊表的數(shù)據(jù)按照【關(guān)聯(lián)列】進(jìn)行選取,與【關(guān)聯(lián)列】相同的數(shù)據(jù)會(huì)被選取,不同的數(shù)據(jù)不會(huì)被選取。選取之后,兩個(gè)表的數(shù)據(jù)按照交叉聯(lián)結(jié)的方式合并展示。

具體的寫法與左聯(lián)結(jié)類似,我這里就不再舉例了,大家可以自己打開Navicat寫一寫。

全聯(lián)結(jié)

全聯(lián)結(jié)會(huì)返回兩個(gè)表的所有行。當(dāng)A表【關(guān)聯(lián)列】的值與B表【關(guān)聯(lián)列】的值相等時(shí),按照交叉聯(lián)結(jié)合并顯示。

當(dāng)A表【關(guān)聯(lián)列】的值與B表【關(guān)聯(lián)列】的值不相等時(shí),另一個(gè)表中對(duì)應(yīng)地方的值用控制來填充。(類似左聯(lián)結(jié)和右聯(lián)結(jié)的結(jié)合)

舉個(gè)例子:

全聯(lián)結(jié)后顯示的結(jié)果為:

說明:MYSQL是不支持全聯(lián)結(jié)的。一般來說,全聯(lián)結(jié)應(yīng)用場(chǎng)景也不多。

3. 案例解答

回到文章一開始的問題:

假設(shè)你在做一款貸款產(chǎn)品,這里有兩張表:用戶表(userinfo)、借款還款表(loanapp)。你想查詢所有用戶的借款總筆數(shù)、借款總金額,就需要以用戶作為關(guān)聯(lián)條件,從三張表里面查找相應(yīng)的數(shù)據(jù)進(jìn)行分析。具體如何實(shí)現(xiàn)?

說明:遇到問題的時(shí)候,一定不能上來就寫SQL語句,這里有一個(gè)三步走分析模型,分享給大家:

1. 拆解問題—2. 寫出分析思路—3. 寫出對(duì)應(yīng)的SQL字句

1. 拆解問題

以上問題拆分成三個(gè)關(guān)鍵部分:所有用戶,借款總筆數(shù),借款總金額

2. 分析思路

所有用戶:用戶ID,用戶姓名,在userinfo查詢

借款總筆數(shù):按照用戶ID分組,對(duì)借款編號(hào)按照筆數(shù)計(jì)數(shù)(count)

借款總金額:按照用戶ID分組,對(duì)借款金額求和(sum)

3. 寫出SQL語句

selecta.ID,a.姓名,b.ID,count(借款編號(hào))as借款總筆數(shù),sum(借款金額)as借款總金額fromuserinfoasaleftjoinloanappasbona.ID = B.ID

groupbya.ID;

到此為止,簡單查詢和多表查詢告一段落。在以后的文章中,我會(huì)盡量舉一些工作中的實(shí)例,由淺入深,與大家一起深入掌握這門語言。接下來將分享復(fù)雜查詢,和一些實(shí)戰(zhàn)數(shù)據(jù)分析。如果有寫的不對(duì)的地方,歡迎指正。也希望你持續(xù)關(guān)注,公號(hào):數(shù)據(jù)產(chǎn)品經(jīng)理之路。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容