您好,登錄后才能下訂單哦!
這篇文章主要介紹了MySQL中邏輯查詢的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
在MySQL中,查詢是用于構建DELETE、UPDATE的基礎,因為你要刪除或者更新他們時,首先就是要查出這些記錄,所以SELECT顯的尤為重要,對于查詢處理,可以分為邏輯查詢和物理查詢,邏輯查詢表示執行SELECT語句時應該產生什么樣的結果,而物理查詢表示MySQL如何得到這個結果的。
本章來說一下邏輯查詢。
在SQL語句中,最先處理的就是FROM語句,最后執行的是LIMIT語句,如果把所有的語句都用上,如GROUP BY、ORDER BY,那么大致可以分為10個步驟,如下所示,每個操作都會產生一張虛擬表。
(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
下面通過一個實際例子來分析一下,首先創建兩張表,用戶和訂單。
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);
好,現在來查詢一下來自內蒙,且訂單數量小于3的用戶,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語句前后的兩張表進行笛卡爾乘積,那么什么是笛卡爾乘積?舉個例子來說,假設集合A={a, b},集合B={0, 1, 2},則兩個集合的笛卡爾積為{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。
所以,對應上面的數據,最終會產生一張虛擬表VT1,他將包含35行數據,具體數據如下所示。
userId | userName | city | orderId | userId |
---|---|---|---|---|
1 | 張三 | 內蒙 | 10001 | 1 |
1 | 張三 | 內蒙 | 10002 | 1 |
1 | 張三 | 內蒙 | 10003 | 4 |
1 | 張三 | 內蒙 | 10005 | 1 |
1 | 張三 | 內蒙 | 10006 | 1 |
1 | 張三 | 內蒙 | 10005 | 4 |
1 | 張三 | 內蒙 | 10007 | 2 |
.................. | ||||
5 | 金甲戰士 | 內蒙 | 10001 | 1 |
5 | 金甲戰士 | 內蒙 | 10002 | 1 |
2. ON過濾器
下一步,通過ON后面的添加過濾掉不需要的數據,在上述SQL中,條件是user.userId = orders.userId
,所以通過上面生成的虛擬表VT1,除去不相關的數據,生成新的虛擬表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.添加外部行
這一步只有在連接類型為OUTER JOIN才發生。
LEFT OUTER JOIN把左表記為保留表,RIGHT OUTER JOIN把右表作為保留表,FULL OUTER JOIN表示都作為保留表,添加外部行的工作就是在上一步的基礎上添加保留表中被過濾條件過濾掉的數據,非保留表的數據被賦值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過濾器
這一步很簡單,條件為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 分組
這步將上一個步驟進行分組,并生成新的虛擬表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是查詢中最先被指定的部分,但是直到這里才真正進行處理,在這一步,將SELECT中指定的列從上一步產生的虛擬表中選出。
8.應用DISTINCT
如果查詢語句中存在DISTINCT子句,則會創建一張內存臨時表,這張內存臨時表的表結構和上一步產生的虛擬表一樣,不同的是對進行DISTINCT操作的列增加了一個唯一索引,以此來去除重復數據。
另外對使用了GROUP BY語句的查詢,再使用DISTINCT是多余的,因為已經進行了分組,不會移除任何行。
9.排序和LIMIT
最后就是排序,返回新的虛擬表。結果如下。
+--------------+-------+ | userName | total | +--------------+-------+ | 李四 | 1 | | 金甲戰士 | 0 | +--------------+-------+
但是在本例子中沒有使用到LIMIT,如果使用到了,那么則從選出指定位置開始的指定行數
感謝你能夠認真閱讀完這篇文章,希望小編分享的“MySQL中邏輯查詢的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。