深入學(xué)習(xí)MySQL中的邏輯查詢(xún)

查詢(xún)是mysql中的最頻繁操作,它也是用于構(gòu)建delete、update的基礎(chǔ);而查詢(xún)處理可分為邏輯查詢(xún)和物理查詢(xún)。今天我們就來(lái)給大家詳細(xì)介紹一下邏輯查詢(xún),希望對(duì)大家有所幫助!

深入學(xué)習(xí)MySQL中的邏輯查詢(xún)

mysql中,查詢(xún)是用于構(gòu)建DELETE、UPDATE的基礎(chǔ),因?yàn)槟阋獎(jiǎng)h除或者更新他們時(shí),首先就是要查出這些記錄,所以SELECT顯的尤為重要,對(duì)于查詢(xún)處理,可以分為邏輯查詢(xún)和物理查詢(xún),邏輯查詢(xún)表示執(zhí)行SELECT語(yǔ)句時(shí)應(yīng)該產(chǎn)生什么樣的結(jié)果,而物理查詢(xún)表示MySQL如何得到這個(gè)結(jié)果的。【相關(guān)推薦:mysql視頻教程

本章來(lái)說(shuō)一下邏輯查詢(xún)。

在SQL語(yǔ)句中,最先處理的就是FROM語(yǔ)句,最后執(zhí)行的是LIMIT語(yǔ)句,如果把所有的語(yǔ)句都用上,如GROUP BY、ORDER BY,那么大致可以分為10個(gè)步驟,如下所示,每個(gè)操作都會(huì)產(chǎn)生一張?zhí)摂M表。

(7)?select?(8)distinct<select_list>  (1)?from?<left> (3)?<join_type>?join?<right_table> (2)????on (4)?where? (5)?group?by (6)?having (9)?order?by (10)?limit</right_table></join_type></left></select_list>

下面通過(guò)一個(gè)實(shí)際例子來(lái)分析一下,首先創(chuàng)建兩張表,用戶(hù)和訂單。

mysql&gt;?create?table?user?(userId?int(11),userName?varchar(255),city?varchar(255),?primary?key?(userId)); Query?OK,?0?rows?affected,?1?warning?(0.05?sec)   mysql&gt;?create?table?orders(orderId?int(11)?,userId?int(11)?,primary?key?(orderId)); Query?OK,?0?rows?affected,?2?warnings?(0.05?sec)

插入數(shù)據(jù)。

insert?user?values(1,"張三","內(nèi)蒙"); insert?user?values(2,"李四","內(nèi)蒙"); insert?user?values(3,"王五","北京"); insert?user?values(4,"迪迦","西藏"); insert?user?values(5,"金甲戰(zhàn)士","內(nèi)蒙");  insert?orders?values(10001,1); insert?orders?values(10002,1); insert?orders?values(10003,4); insert?orders?values(10004,1); insert?orders?values(10005,1); insert?orders?values(10006,4); insert?orders?values(10007,2);

好,現(xiàn)在來(lái)查詢(xún)一下來(lái)自?xún)?nèi)蒙,且訂單數(shù)量小于3的用戶(hù),SQL如下。

mysql&gt;?select?userName,count(orders.orderId)?as?total?from?user? left?join?orders?on?user.userId?=?orders.userId? where?city="內(nèi)蒙"? group?by?user.userId? having?count(orders.orderId)<p>有數(shù)據(jù)有SQL,下面分析一下具體流程。</p><p><strong><span style="font-size: 18px;">1. 笛卡爾乘積</span></strong></p><p>首先要做的是對(duì)FROM語(yǔ)句前后的兩張表進(jìn)行笛卡爾乘積,那么什么是笛卡爾乘積?舉個(gè)例子來(lái)說(shuō),假設(shè)集合A={a, b},集合B={0, 1, 2},則兩個(gè)集合的笛卡爾積為{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。</p><p>所以,對(duì)應(yīng)上面的數(shù)據(jù),最終會(huì)產(chǎn)生一張?zhí)摂M表VT1,他將包含35行數(shù)據(jù),具體數(shù)據(jù)如下所示。</p>
userId userName city orderId userId
1 張三 內(nèi)蒙 10001 1
1 張三 內(nèi)蒙 10002 1
1 張三 內(nèi)蒙 10003 4
1 張三 內(nèi)蒙 10005 1
1 張三 內(nèi)蒙 10006 1
1 張三 內(nèi)蒙 10005 4
1 張三 內(nèi)蒙 10007 2
………………
5 金甲戰(zhàn)士 內(nèi)蒙 10001 1
5 金甲戰(zhàn)士 內(nèi)蒙 10002 1

2. ON過(guò)濾器

下一步,通過(guò)ON后面的添加過(guò)濾掉不需要的數(shù)據(jù),在上述SQL中,條件是user.userId = orders.userId ,所以通過(guò)上面生成的虛擬表VT1,除去不相關(guān)的數(shù)據(jù),生成新的虛擬表VT2,最終的結(jié)果如下。

+--------+--------------+--------+---------+--------+ |?userId?|?userName?????|?city???|?orderId?|?userId?| +--------+--------------+--------+---------+--------+ |??????1?|?張三?????????|?內(nèi)蒙???|???10005?|??????1?| |??????1?|?張三?????????|?內(nèi)蒙???|???10004?|??????1?| |??????1?|?張三?????????|?內(nèi)蒙???|???10002?|??????1?| |??????1?|?張三?????????|?內(nèi)蒙???|???10001?|??????1?| |??????2?|?李四?????????|?內(nèi)蒙???|???10007?|??????2?| |??????3?|?王五?????????|?北京???|????NULL?|???NULL?| |??????4?|?迪迦?????????|?西藏???|???10006?|??????4?| |??????4?|?迪迦?????????|?西藏???|???10003?|??????4?| |??????5?|?金甲戰(zhàn)士?????|?內(nèi)蒙???|????NULL?|???NULL?| +--------+--------------+--------+---------+--------+

3.添加外部行

這一步只有在連接類(lèi)型為OUTER JOIN才發(fā)生。

LEFT OUTER JOIN把左表記為保留表,RIGHT OUTER JOIN把右表作為保留表,F(xiàn)ULL OUTER JOIN表示都作為保留表,添加外部行的工作就是在上一步的基礎(chǔ)上添加保留表中被過(guò)濾條件過(guò)濾掉的數(shù)據(jù),非保留表的數(shù)據(jù)被賦值NULL。

最終生成下面的結(jié)果,記為虛擬表VT3。

+--------+--------------+--------+---------+--------+ |?userId?|?userName?????|?city???|?orderId?|?userId?| +--------+--------------+--------+---------+--------+ |??????1?|?張三?????????|?內(nèi)蒙???|???10005?|??????1?| |??????1?|?張三?????????|?內(nèi)蒙???|???10004?|??????1?| |??????1?|?張三?????????|?內(nèi)蒙???|???10002?|??????1?| |??????1?|?張三?????????|?內(nèi)蒙???|???10001?|??????1?| |??????2?|?李四?????????|?內(nèi)蒙???|???10007?|??????2?| |??????3?|?王五?????????|?北京???|????NULL?|???NULL?| |??????4?|?迪迦?????????|?西藏???|???10006?|??????4?| |??????4?|?迪迦?????????|?西藏???|???10003?|??????4?| |??????5?|?金甲戰(zhàn)士?????|?內(nèi)蒙???|????NULL?|???NULL?| +--------+--------------+--------+---------+--------+

4. WHERE過(guò)濾器

這一步很簡(jiǎn)單,條件為city=”內(nèi)蒙” ,即只保留下city為內(nèi)蒙的列,并生成新的虛擬表VT4。最終結(jié)果如下。

+--------+--------------+--------+---------+--------+ |?userId?|?userName?????|?city???|?orderId?|?userId?| +--------+--------------+--------+---------+--------+ |??????1?|?張三?????????|?內(nèi)蒙???|???10005?|??????1?| |??????1?|?張三?????????|?內(nèi)蒙???|???10004?|??????1?| |??????1?|?張三?????????|?內(nèi)蒙???|???10002?|??????1?| |??????1?|?張三?????????|?內(nèi)蒙???|???10001?|??????1?| |??????2?|?李四?????????|?內(nèi)蒙???|???10007?|??????2?| |??????5?|?金甲戰(zhàn)士?????|?內(nèi)蒙???|????NULL?|???NULL?| +--------+--------------+--------+---------+--------+

5. GROUP BY 分組

這步將上一個(gè)步驟進(jìn)行分組,并生成新的虛擬表VT5,結(jié)果如下。

+--------+--------------+--------+ |?userId?|?userName?????|?city???| +--------+--------------+--------+ |??????1?|?張三?????????|?內(nèi)蒙???| |??????2?|?李四?????????|?內(nèi)蒙???| |??????5?|?金甲戰(zhàn)士?????|?內(nèi)蒙???| +--------+--------------+--------+

6.HAVING篩選

分完組,我們就可以篩選了,選出count(orders.orderId)

|?userId?|?userName?????|?city???|?count(orders.orderId)?| +--------+--------------+--------+-----------------------+ |??????2?|?李四?????????|?內(nèi)蒙???|?????????????????????1?| |??????5?|?金甲戰(zhàn)士?????|?內(nèi)蒙???|?????????????????????0?| +--------+--------------+--------+-----------------------+

7.處理SELECT列表

雖然SELECT是查詢(xún)中最先被指定的部分,但是直到這里才真正進(jìn)行處理,在這一步,將SELECT中指定的列從上一步產(chǎn)生的虛擬表中選出。

8.應(yīng)用DISTINCT

如果查詢(xún)語(yǔ)句中存在DISTINCT子句,則會(huì)創(chuàng)建一張內(nèi)存臨時(shí)表,這張內(nèi)存臨時(shí)表的表結(jié)構(gòu)和上一步產(chǎn)生的虛擬表一樣,不同的是對(duì)進(jìn)行DISTINCT操作的列增加了一個(gè)唯一索引,以此來(lái)去除重復(fù)數(shù)據(jù)。

另外對(duì)使用了GROUP BY語(yǔ)句的查詢(xún),再使用DISTINCT是多余的,因?yàn)橐呀?jīng)進(jìn)行了分組,不會(huì)移除任何行。

9.排序和LIMIT

最后就是排序,返回新的虛擬表。結(jié)果如下。

+--------------+-------+ |?userName?????|?total?| +--------------+-------+ |?李四?????????|?????1?| |?金甲戰(zhàn)士?????|?????0?| +--------------+-------+

但是在本例子中沒(méi)有使用到LIMIT,如果使用到了,那么則從選出指定位置開(kāi)始的指定行數(shù),

原文地址:https://juejin.cn/post/7000739902937628679作者:i聽(tīng)風(fēng)逝夜

更多編程相關(guān)知識(shí),請(qǐng)?jiān)L問(wèn):mysql視頻教程!!

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊6 分享