<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SQL查詢的順序是怎么樣的?

          共 3972字,需瀏覽 8分鐘

           ·

          2021-07-17 17:32


          作者 | Julia Evans      


          顯然很多SQL查詢都是從SELECT開始的(實際上本文只是關(guān)注SELECT查詢,而不是INSERT或其它別的什么)。

          但是!昨天我正在做窗口函數(shù)的解釋說明,并且我發(fā)現(xiàn)自己在谷歌上搜索“你能根據(jù)窗口函數(shù)的結(jié)果進(jìn)行過濾嗎”。比如 — 你能在WHERE、HAVING或者其它地方過濾窗口函數(shù)的結(jié)果嗎?

          最后我得出的結(jié)論是:“窗口函數(shù)必須在WHERE和GROUP BY之后運行,所以你做不到”。但這讓我想到了一個更大的問題 — SQL查詢的實際運行順序是什么?

          這是我憑直覺就知道的事情(“我肯定知道!我已經(jīng)編寫了至少10000個SQL查詢,其中一些非常復(fù)雜!),但我很難真正地準(zhǔn)確說出順序是什么。



          SQL查詢按此順序進(jìn)行


          這就是我查找到的順序!(SELECT并不是在第一步執(zhí)行,而是到第五步才執(zhí)行)

          這里是一篇推特 https://twitter.com/b0rk/status/1179449535938076673

          (我真的很想找到一種比“sql查詢按此順序發(fā)生/運行”更準(zhǔn)確的表達(dá)方式,但我還沒想出來。)


          在非圖形格式中,其順序為:








          l FROM/JOIN 和所有的 ON 條件l WHEREl GROUP BYl HAVINGl SELECT(包括窗口函數(shù))l ORDER BYl LIMIT



          圖解此圖有助于你做出回答


          此圖是關(guān)于SQL查詢的語義的 — 你可以通過它,對給定查詢將返回什么結(jié)果進(jìn)行推理,并回答如下問題:

          • 我能在一個GROUP BY的結(jié)果上執(zhí)行WHERE么?(不行!WHERE發(fā)生在GROUP BY之前?。?/span>

          • 我可以根據(jù)窗口函數(shù)的結(jié)果進(jìn)行過濾嗎(不行!窗口函數(shù)發(fā)生在SELECT中,它發(fā)生在WHERE和GROUP BY之后)

          • 我可以基于GROUP BY中所做的來進(jìn)行ORDER BY么?(可以!ORDER BY是最后執(zhí)行的基本步驟,你可以根據(jù)任何東西做ORDER BY?。?/span>

          • LIMIT何時執(zhí)行?(在最后?。?/span>



          數(shù)據(jù)庫引擎實際并不是按這個順序運行查詢


          因為它實現(xiàn)了一系列優(yōu)化以使查詢運行得更快 — 我們稍后將在本文中討論這一點。

          所以:

          • 當(dāng)你只想了解哪些查詢是有效的,以及如何推理給定查詢的結(jié)果時,可以使用此圖。

          • 你不應(yīng)該使用此圖來解釋查詢性能或任何有關(guān)索引的事情,那是一個復(fù)雜得多的問題,涉及更多變量。

           


          混淆因素:列別名


          有人在Twitter上指出,許多SQL實現(xiàn)允許你使用以下語法:




          SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*)FROM tableGROUP 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 tableGROUP BY CONCAT(first_name, ' ', last_name)

          并且首先運行GROUP BY。

          你的數(shù)據(jù)庫引擎肯定還會在開始運行查詢之前執(zhí)行一系列檢查,確保你在SELECT和GROUP BY中放置的內(nèi)容合在一起是有意義的,因此在開始制定執(zhí)行計劃之前,它必須將查詢作為一個整體來查看。

           


          查詢實際上不是按此順序運行的(優(yōu)化?。?/span>


          實際上,數(shù)據(jù)庫引擎并不是真的通過連接、然后過濾、然后再分組來運行查詢,因為它們實現(xiàn)了一系列優(yōu)化,只要重新排列執(zhí)行順序不改變查詢結(jié)果,就可以重排以使查詢運行得更快。

          一個簡單的例子說明了為什么需要以不同的順序運行查詢以使其快速運行,在這個查詢中:




          SELECT * FROMowners LEFT JOIN cats ON owners.id = cats.ownerWHERE cats.name = 'mr darcy'

          如果你只需要查找3個名為“mr darcy”的貓,那么執(zhí)行整個左連接并匹配這兩個表中的所有行是非常愚蠢的 —— 首先對名為“mr darcy”的貓進(jìn)行一些篩選要快得多。在這種情況下,先進(jìn)行過濾不會改變查詢結(jié)果!

          實際上,數(shù)據(jù)庫引擎還實現(xiàn)了許多其它優(yōu)化,這些優(yōu)化可能會使它們以不同的順序運行查詢,但不能再說了,老實講,這方面我不是專家。



          LINQ以FROM開始查詢


          LINQ(一種C#和VB.NET中的查詢語法)使用的順序為FROM ... WHERE ... SELECT。下面是一個LINQ查詢的示例:




          var teenAgerStudent = from s in studentList                      where s.Age > 12 && s.Age < 20                      select s;

          pandas(我喜歡的數(shù)據(jù)治理工具:https://github.com/jvns/pandas-cookbook)也基本上是這樣工作的,盡管你不需要使用這種精確的順序 — 我經(jīng)常會這樣編寫pandas代碼:








          df = thing1.join(thing2)      # like a JOINdf = df[df.created_at > 1000] # like a WHEREdf = df.groupby('something', num_yes = ('yes', 'sum')) # like a GROUP BYdf = df[df.num_yes > 2]       # like a HAVING, filtering on the result of a GROUP BYdf = df[['num_yes', 'something1', 'something']] # pick the columns I want to display, like a SELECTdf.sort_values('sometthing', ascending=True)[:30] # ORDER BY and LIMITdf[:30]

          這并不是因為pandas對如何編寫代碼強(qiáng)加了任何特定規(guī)則。只是按照J(rèn)OIN / WHERE / GROUP BY / HAVING的順序編寫代碼通常好理解。(不過,我經(jīng)常會先放一個WHERE來提高性能,而且我認(rèn)為大多數(shù)數(shù)據(jù)庫引擎實際也會先執(zhí)行WHERE)

          在R的dplyr中,你還能使用不同的語法來查詢諸如Postgres、MySQL或SQLite等SQL數(shù)據(jù)庫,它們的順序也更符合邏輯。

          不知道這一點令我自己著實驚訝

          我寫了這樣一篇博文,因為當(dāng)我發(fā)現(xiàn)這個順序的時候非常驚訝,我以前從來沒有看到過它被這樣寫下來 — 它基本上解釋了我憑直覺所知道的,關(guān)于為什么一些查詢被允許而另一些不被允許的一切。所以我想把它寫下來,希望它能幫助其他人理解如何編寫SQL查詢。


          瀏覽 51
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费看抠逼| 操123| 成人中文字幕在线视频 | 亚洲成人毛片 | 99视频自拍 |