解析 mysql_MySQL的sql解析
首先看一下示例語句
SELECT DISTINCT
< select_list >
FROM
< left_table > < join_type >
JOIN < right_table > ON < join_condition >
WHERE
< where_condition >
GROUP BY
< group_by_list >
HAVING
< having_condition >
ORDER BY
< order_by_condition >
LIMIT < limit_number >
然而它的執(zhí)行順序是這樣的
1 FROM
2 ON
3 JOIN ?第二步和第三步會(huì)循環(huán)執(zhí)行
4 WHERE ?第四步會(huì)循環(huán)執(zhí)行,多個(gè)條件的執(zhí)行順序是從左往右的。
5 GROUP BY
6 HAVING
7 SELECT 分組之后才會(huì)執(zhí)行SELECT
8 DISTINCT
9 ORDER BY
10 LIMIT 前9步都是SQL92標(biāo)準(zhǔn)語法。limit是MySQL的獨(dú)有語法
來看一個(gè)例子
假設(shè)有表1和表2
table1
table2
1、from
2個(gè)表聯(lián)合查詢得到他們的笛卡爾積CROSS JOIN,產(chǎn)生 虛表VT1
2、ON過濾
對(duì) 虛表VT1 進(jìn)行ON篩選,只有那些符合的行才會(huì)被記錄在虛表VT2中。
注意:這里因?yàn)檎Z法限制,使用了‘WHERE‘代替,從中讀者也可以感受到兩者之間微妙的關(guān)系;
3.OUTER JOIN添加外部列
如果指定了 OUTER JOIN(比如left join、 right join) ,那么 保留表中未匹配的行 就會(huì)作為外部行 添加 到 虛
擬表VT2 中,產(chǎn)生 虛擬表VT3 。
如果FROM子句中包含兩個(gè)以上的表的話,那么就會(huì)對(duì)上一個(gè)join連接產(chǎn)生的結(jié)果VT3和下一個(gè)表重復(fù)執(zhí)行步驟1~3
這三個(gè)步驟,一直到處理完所有的表為止
4.WHERE
對(duì) 虛擬表VT3 進(jìn)行WHERE條件過濾。只有符合的記錄才會(huì)被插入到 虛擬表VT4 中。
5.GROUP BY
根據(jù)group by子句中的列,對(duì)VT4中的記錄進(jìn)行分組操作,產(chǎn)生 虛擬表VT5 。
注意:
其后處理過程的語句,如SELECT,HAVING,所用到的列必須包含在GROUP BY中。對(duì)于沒有出現(xiàn)的,得用聚合函
數(shù);
原因:
GROUP BY改變了對(duì)表的引用,將其轉(zhuǎn)換為新的引用方式,能夠?qū)ζ溥M(jìn)行下一級(jí)邏輯操作的列會(huì)減少;
6.HAVING
對(duì) 虛擬表VT5 應(yīng)用having過濾,只有符合的記錄才會(huì)被 插入到 虛擬表VT6 中。
7.SELECT
這個(gè)子句對(duì)SELECT子句中的元素進(jìn)行處理,生成VT5表。
(5-J1)計(jì)算表達(dá)式 計(jì)算SELECT 子句中的表達(dá)式,生成VT5-J1
8.DISTINCT
尋找VT5-1中的重復(fù)列,并刪掉,生成VT5-J2
如果在查詢中指定了DISTINCT子句,則會(huì)創(chuàng)建一張內(nèi)存臨時(shí)表(如果內(nèi)存放不下,就需要存放在硬盤了)。這張
臨時(shí)表的表結(jié)構(gòu)和上一步產(chǎn)生的虛擬表VT5是一樣的,不同的是對(duì)進(jìn)行DISTINCT操作的列增加了一個(gè)唯一索引,以
此來除重復(fù)數(shù)據(jù)
9.ORDER BY
從 VT5-J2 中的表中,根據(jù)ORDER BY 子句的條件對(duì)結(jié)果進(jìn)行排序,生成VT6表。
注意:
唯一可使用SELECT中別名的地方
10.LIMIT(MySQL特有)
LIMIT子句從上一步得到的 VT6虛擬表 中選出從指定位置開始的指定行數(shù)據(jù)
注意:
offset 和 rows 的正負(fù)帶來的影響;
當(dāng)偏移量很大時(shí)效率是很低的,可以這么做:
采用子查詢的方式優(yōu)化 ,在子查詢里先從索引獲取到最大id,然后倒序排,再取N行結(jié)果集
采用INNER JOIN優(yōu)化 ,JOIN子句里也優(yōu)先從索引獲取ID列表,然后直接關(guān)聯(lián)查詢獲得最終結(jié)果
解析順序總結(jié)
流程分析
1. ?FROM(將最近的兩張表,進(jìn)行笛卡爾積)---VT1
2. ?ON(將VT1按照它的條件進(jìn)行過濾)---VT2
3. ?LEFT JOIN(保留左表的記錄)---VT3
4. ?WHERE(過濾VT3中的記錄)--VT4…VTn
5. ?GROUP BY(對(duì)VT4的記錄進(jìn)行分組)---VT5
6. ?HAVING(對(duì)VT5中的記錄進(jìn)行過濾)---VT6
7. ?SELECT(對(duì)VT6中的記錄,選取指定的列)--VT7
8. ?ORDER BY(對(duì)VT7的記錄進(jìn)行排序)--VT8
9. ?LIMIT(對(duì)排序之后的值進(jìn)行分頁)--MySQL特有的語法
流程說明:
單表查詢:根據(jù) WHERE 條件過濾表中的記錄,形成中間表(這個(gè)中間表對(duì)用戶是不可見的);然后根據(jù)
SELECT 的選擇列選擇相應(yīng)的列進(jìn)行返回最終結(jié)果。
兩表連接查詢:對(duì)兩表求積(笛卡爾積)并用 ON 條件和連接連接類型進(jìn)行過濾形成中間表;然后根據(jù)
WHERE條件過濾中間表的記錄,并根據(jù) SELECT 指定的列返回查詢結(jié)果。
笛卡爾積:行相乘、列相加
多表連接查詢:先對(duì)第一個(gè)和第二個(gè)表按照兩表連接做查詢,然后用查詢結(jié)果和第三個(gè)表做連接查詢,以此
類推,直到所有的表都連接上為止,最終形成一個(gè)中間的結(jié)果表,然后根據(jù)WHERE條件過濾中間表的記錄,
并根據(jù)SELECT指定的列返回查詢結(jié)果。
總結(jié)
以上是生活随笔為你收集整理的解析 mysql_MySQL的sql解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 八卦一下“笑点低”到底低成什么样?什么才
- 下一篇: mysql第三章关系模型_一个MySQL