SQL查询是从Select开始的吗?
作者 | Julia Evans? ? ??
譯者 | 王雪迎? ? ?責編 | 孫勝? ? ? ? ? ? ??
出品 | CSDN(ID:CSDNnews)
好吧,顯然很多SQL查詢都是從SELECT開始的(實際上本文只是關注SELECT查詢,而不是INSERT或其它別的什么)。
但是!昨天我正在做窗口函數(shù)的解釋說明,并且我發(fā)現(xiàn)自己在谷歌上搜索“你能根據(jù)窗口函數(shù)的結果進行過濾嗎”。比如 — 你能在WHERE、HAVING或者其它地方過濾窗口函數(shù)的結果嗎?
最后我得出的結論是:“窗口函數(shù)必須在WHERE和GROUP BY之后運行,所以你做不到”。但這讓我想到了一個更大的問題 — SQL查詢的實際運行順序是什么?
這是我憑直覺就知道的事情(“我肯定知道!我已經(jīng)編寫了至少10000個SQL查詢,其中一些非常復雜!),但我很難真正地準確說出順序是什么。
1、SQL查詢按此順序進行
這就是我查找到的順序!(SELECT并不是在第一步執(zhí)行,而是到第五步才執(zhí)行)
(這里是一篇推特:?https://twitter.com/b0rk/status/1179449535938076673)
(我真的很想找到一種比“sql查詢按此順序發(fā)生/運行”更準確的表達方式,但我還沒想出來。)
在非圖形格式中,其順序為:
l FROM/JOIN 和所有的 ON 條件 l WHERE l GROUP BY l HAVING l SELECT(包括窗口函數(shù)) l ORDER BY l LIMIT2、圖解此圖有助于你做出回答
此圖是關于SQL查詢的語義的 — 你可以通過它,對給定查詢將返回什么結果進行推理,并回答如下問題:
我能在一個GROUP BY的結果上執(zhí)行WHERE么?(不行!WHERE發(fā)生在GROUP BY之前!)
我可以根據(jù)窗口函數(shù)的結果進行過濾嗎(不行!窗口函數(shù)發(fā)生在SELECT中,它發(fā)生在WHERE和GROUP BY之后)
我可以基于GROUP BY中所做的來進行ORDER BY么?(可以!ORDER BY是最后執(zhí)行的基本步驟,你可以根據(jù)任何東西做ORDER BY!)
LIMIT何時執(zhí)行?(在最后!)
3、數(shù)據(jù)庫引擎實際并不是按這個順序運行查詢
因為它實現(xiàn)了一系列優(yōu)化以使查詢運行得更快 — 我們稍后將在本文中討論這一點。
所以:
當你只想了解哪些查詢是有效的,以及如何推理給定查詢的結果時,可以使用此圖。
你不應該使用此圖來解釋查詢性能或任何有關索引的事情,那是一個復雜得多的問題,涉及更多變量。
?
4、混淆因素:列別名
有人在Twitter上指出,許多SQL實現(xiàn)允許你使用以下語法:
SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*) FROM table GROUP BY full_name此查詢使其看起來像是在SELECT之后才發(fā)生GROUP BY,即使GROUP BY先執(zhí)行,因為GROUP BY引用了SELECT中的別名。但是要使GROUP BY發(fā)揮作用,其實并不需要在SELECT之后才運行 — 數(shù)據(jù)庫引擎只要將查詢重寫為:
SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*) FROM table GROUP BY CONCAT(first_name, ' ', last_name)并且首先運行GROUP BY。
你的數(shù)據(jù)庫引擎肯定還會在開始運行查詢之前執(zhí)行一系列檢查,確保你在SELECT和GROUP BY中放置的內容合在一起是有意義的,因此在開始制定執(zhí)行計劃之前,它必須將查詢作為一個整體來查看。
?
5、查詢實際上不是按此順序運行的(優(yōu)化!)
實際上,數(shù)據(jù)庫引擎并不是真的通過連接、然后過濾、然后再分組來運行查詢,因為它們實現(xiàn)了一系列優(yōu)化,只要重新排列執(zhí)行順序不改變查詢結果,就可以重排以使查詢運行得更快。
一個簡單的例子說明了為什么需要以不同的順序運行查詢以使其快速運行,在這個查詢中:
SELECT * FROM owners LEFT JOIN cats ON owners.id = cats.owner WHERE cats.name = 'mr darcy'如果你只需要查找3個名為“mr darcy”的貓,那么執(zhí)行整個左連接并匹配這兩個表中的所有行是非常愚蠢的 —— 首先對名為“mr darcy”的貓進行一些篩選要快得多。在這種情況下,先進行過濾不會改變查詢結果!
實際上,數(shù)據(jù)庫引擎還實現(xiàn)了許多其它優(yōu)化,這些優(yōu)化可能會使它們以不同的順序運行查詢,但不能再說了,老實講,這方面我不是專家。
6、LINQ以FROM開始查詢
LINQ(一種C#和VB.NET中的查詢語法)使用的順序為FROM ... WHERE ... SELECT。下面是一個LINQ查詢的示例:
var teenAgerStudent = from s in studentListwhere s.Age > 12 && s.Age < 20select s;pandas(我所喜歡的數(shù)據(jù)治理工具:https://github.com/jvns/pandas-cookbook)也基本上是這樣工作的,盡管你不需要使用這種精確的順序 — 我經(jīng)常會這樣編寫pandas代碼:
df = thing1.join(thing2) # like a JOIN df = df[df.created_at > 1000] # like a WHERE df = df.groupby('something', num_yes = ('yes', 'sum')) # like a GROUP BY df = df[df.num_yes > 2] # like a HAVING, filtering on the result of a GROUP BY df = df[['num_yes', 'something1', 'something']] # pick the columns I want to display, like a SELECT df.sort_values('sometthing', ascending=True)[:30] # ORDER BY and LIMIT df[:30]這并不是因為pandas對如何編寫代碼強加了任何特定規(guī)則。只是按照JOIN / WHERE / GROUP BY / HAVING的順序編寫代碼通常好理解。(不過,我經(jīng)常會先放一個WHERE來提高性能,而且我認為大多數(shù)數(shù)據(jù)庫引擎實際也會先執(zhí)行WHERE)
在R的dplyr中,你還能使用不同的語法來查詢諸如Postgres、MySQL或SQLite等SQL數(shù)據(jù)庫,它們的順序也更符合邏輯。
不知道這一點令我自己著實驚訝
我寫了這樣一篇博文,因為當我發(fā)現(xiàn)這個順序的時候非常驚訝,我以前從來沒有看到過它被這樣寫下來 — 它基本上解釋了我憑直覺所知道的,關于為什么一些查詢被允許而另一些不被允許的一切。所以我想把它寫下來,希望它能幫助其他人理解如何編寫SQL查詢。
原文:https://jvns.ca/blog/2019/10/03/sql-queries-don-t-start-with-select/
最后推薦一下我們的星球:由菜鳥學Python原班人馬建了一個投資星球,匯聚一批喜歡投資的朋友一起分享投資的技巧,不限于基金,股票等其他品種,提高自己的財商,一起讀書打卡,歡迎加入。推薦閱讀:入門:?最全的零基礎學Python的問題? |?零基礎學了8個月的Python??|?實戰(zhàn)項目?|學Python就是這條捷徑干貨:爬取豆瓣短評,電影《后來的我們》?|?38年NBA最佳球員分析?|? ?從萬眾期待到口碑撲街!唐探3令人失望? |?笑看新倚天屠龍記?|?燈謎答題王?|用Python做個海量小姐姐素描圖?|碟中諜這么火,我用機器學習做個迷你推薦系統(tǒng)電影趣味:彈球游戲? |?九宮格? |?漂亮的花?|?兩百行Python《天天酷跑》游戲!AI:?會做詩的機器人?|?給圖片上色?|?預測收入?|?碟中諜這么火,我用機器學習做個迷你推薦系統(tǒng)電影小工具:?Pdf轉Word,輕松搞定表格和水印!?|?一鍵把html網(wǎng)頁保存為pdf!|??再見PDF提取收費!?|?用90行代碼打造最強PDF轉換器,word、PPT、excel、markdown、html一鍵轉換?|?制作一款釘釘?shù)蛢r機票提示器!?|60行代碼做了一個語音壁紙切換器天天看小姐姐!|年度爆款文案1).臥槽!Pdf轉Word用Python輕松搞定!2).學Python真香!我用100行代碼做了個網(wǎng)站,幫人PS旅行圖片,賺個雞腿吃3).首播過億,火爆全網(wǎng),我分析了《乘風破浪的姐姐》,發(fā)現(xiàn)了這些秘密?4).80行代碼!用Python做一個哆來A夢分身?5).你必須掌握的20個python代碼,短小精悍,用處無窮?6).30個Python奇淫技巧集?7).我總結的80頁《菜鳥學Python精選干貨.pdf》,都是干貨?8).再見Python!我要學Go了!2500字深度分析!9).發(fā)現(xiàn)一個舔狗福利!這個Python爬蟲神器太爽了,自動下載妹子圖片點閱讀原文,領AI全套資料!總結
以上是生活随笔為你收集整理的SQL查询是从Select开始的吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习(2305):react之脚手架
- 下一篇: 三级数据库知识点总结