這篇文章主要介紹了中邏輯查詢(xún)的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著(zhù)大家一起了解一下。
在MySQL中,查詢(xún)是用于構建DELETE、UPDATE的基礎,因為你要刪除或者更新他們時(shí),首先就是要查出這些記錄,所以SELECT顯的尤為重要,對于查詢(xún)處理,可以分為邏輯查詢(xún)和物理查詢(xún),邏輯查詢(xún)表示執行SELECT語(yǔ)句時(shí)應該產(chǎn)生什么樣的結果,而物理查詢(xún)表示MySQL如何得到這個(gè)結果的。
本章來(lái)說(shuō)一下邏輯查詢(xún)。
在SQL語(yǔ)句中,最先處理的就是FROM語(yǔ)句,最后執行的是LIMIT語(yǔ)句,如果把所有的語(yǔ)句都用上,如GROUP BY、ORDER BY,那么大致可以分為10個(gè)步驟,如下所示,每個(gè)操作都會(huì )產(chǎn)生一張虛擬表。
(7) select (8)distinct<select_list> (1) from <left table> (3) <join_type> join <right_table> (2) on<條件> (4) where <條件> (5) group by<字段list> (6) having<條件> (9) order by<字段> (10) limit
下面通過(guò)一個(gè)實(shí)際例子來(lái)分析一下,首先創(chuàng )建兩張表,用戶(hù)和訂單。
mysql> 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> create table orders(orderId int(11) ,userId int(11) ,primary key (orderId)); Query OK, 0 rows affected, 2 warnings (0.05 sec)
插入數據。
insert user values(1,"張三","內蒙"); insert user values(2,"李四","內蒙"); insert user values(3,"王五","北京"); insert user values(4,"迪迦","西藏"); insert user values(5,"金甲戰士","內蒙"); 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);
好,現在來(lái)查詢(xún)一下來(lái)自?xún)让?,且訂單數量小?的用戶(hù),SQL如下。
mysql> select userName,count(orders.orderId) as total from user left join orders on user.userId = orders.userId where city="內蒙" group by user.userId having count(orders.orderId)<3 order by total desc; +--------------+-------+ | userName | total | +--------------+-------+ | 李四 | 1 | | 金甲戰士 | 0 | +--------------+-------+ 2 rows in set (0.00 sec)
有數據有SQL,下面分析一下具體流程。
1. 笛卡爾乘積
首先要做的是對FROM語(yǔ)句前后的兩張表進(jìn)行笛卡爾乘積,那么什么是笛卡爾乘積?舉個(gè)例子來(lái)說(shuō),假設集合A={a, b},集合B={0, 1, 2},則兩個(gè)集合的笛卡爾積為{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。
所以,對應上面的數據,最終會(huì )產(chǎn)生一張虛擬表VT1,他將包含35行數據,具體數據如下所示。
2. ON過(guò)濾器
下一步,通過(guò)ON后面的添加過(guò)濾掉不需要的數據,在上述SQL中,條件是user.userId = orders.userId
,所以通過(guò)上面生成的虛擬表VT1,除去不相關(guān)的數據,生成新的虛擬表VT2,最終的結果如下。
+--------+--------------+--------+---------+--------+ | userId | userName | city | orderId | userId | +--------+--------------+--------+---------+--------+ | 1 | 張三 | 內蒙 | 10005 | 1 | | 1 | 張三 | 內蒙 | 10004 | 1 | | 1 | 張三 | 內蒙 | 10002 | 1 | | 1 | 張三 | 內蒙 | 10001 | 1 | | 2 | 李四 | 內蒙 | 10007 | 2 | | 3 | 王五 | 北京 | NULL | NULL | | 4 | 迪迦 | 西藏 | 10006 | 4 | | 4 | 迪迦 | 西藏 | 10003 | 4 | | 5 | 金甲戰士 | 內蒙 | NULL | NULL | +--------+--------------+--------+---------+--------+
3.添加外部行
這一步只有在連接類(lèi)型為OUTER JOIN才發(fā)生。
LEFT OUTER JOIN把左表記為保留表,RIGHT OUTER JOIN把右表作為保留表,FULL OUTER JOIN表示都作為保留表,添加外部行的工作就是在上一步的基礎上添加保留表中被過(guò)濾條件過(guò)濾掉的數據,非保留表的數據被賦值NULL。
最終生成下面的結果,記為虛擬表VT3。
+--------+--------------+--------+---------+--------+ | userId | userName | city | orderId | userId | +--------+--------------+--------+---------+--------+ | 1 | 張三 | 內蒙 | 10005 | 1 | | 1 | 張三 | 內蒙 | 10004 | 1 | | 1 | 張三 | 內蒙 | 10002 | 1 | | 1 | 張三 | 內蒙 | 10001 | 1 | | 2 | 李四 | 內蒙 | 10007 | 2 | | 3 | 王五 | 北京 | NULL | NULL | | 4 | 迪迦 | 西藏 | 10006 | 4 | | 4 | 迪迦 | 西藏 | 10003 | 4 | | 5 | 金甲戰士 | 內蒙 | NULL | NULL | +--------+--------------+--------+---------+--------+
4. WHERE過(guò)濾器
這一步很簡(jiǎn)單,條件為city="內蒙"
,即只保留下city為內蒙的列,并生成新的虛擬表VT4。最終結果如下。
+--------+--------------+--------+---------+--------+ | userId | userName | city | orderId | userId | +--------+--------------+--------+---------+--------+ | 1 | 張三 | 內蒙 | 10005 | 1 | | 1 | 張三 | 內蒙 | 10004 | 1 | | 1 | 張三 | 內蒙 | 10002 | 1 | | 1 | 張三 | 內蒙 | 10001 | 1 | | 2 | 李四 | 內蒙 | 10007 | 2 | | 5 | 金甲戰士 | 內蒙 | NULL | NULL | +--------+--------------+--------+---------+--------+
5. GROUP BY 分組
這步將上一個(gè)步驟進(jìn)行分組,并生成新的虛擬表VT5,結果如下。
+--------+--------------+--------+ | userId | userName | city | +--------+--------------+--------+ | 1 | 張三 | 內蒙 | | 2 | 李四 | 內蒙 | | 5 | 金甲戰士 | 內蒙 | +--------+--------------+--------+
6.HAVING篩選
分完組,我們就可以篩選了,選出count(orders.orderId)<3
的數據即可,最終結果如下。
| userId | userName | city | count(orders.orderId) | +--------+--------------+--------+-----------------------+ | 2 | 李四 | 內蒙 | 1 | | 5 | 金甲戰士 | 內蒙 | 0 | +--------+--------------+--------+-----------------------+
7.處理SELECT列表
雖然SELECT是查詢(xún)中最先被指定的部分,但是直到這里才真正進(jìn)行處理,在這一步,將SELECT中指定的列從上一步產(chǎn)生的虛擬表中選出。
8.應用DISTINCT
如果查詢(xún)語(yǔ)句中存在DISTINCT子句,則會(huì )創(chuàng )建一張內存臨時(shí)表,這張內存臨時(shí)表的表結構和上一步產(chǎn)生的虛擬表一樣,不同的是對進(jìn)行DISTINCT操作的列增加了一個(gè)唯一索引,以此來(lái)去除重復數據。
另外對使用了GROUP BY語(yǔ)句的查詢(xún),再使用DISTINCT是多余的,因為已經(jīng)進(jìn)行了分組,不會(huì )移除任何行。
9.排序和LIMIT
最后就是排序,返回新的虛擬表。結果如下。
+--------------+-------+ | userName | total | +--------------+-------+ | 李四 | 1 | | 金甲戰士 | 0 | +--------------+-------+
但是在本例子中沒(méi)有使用到LIMIT,如果使用到了,那么則從選出指定位置開(kāi)始的指定行數
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站