溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

join?on和where執(zhí)行順序是什么

發(fā)布時間:2023-03-06 11:29:46 來源:億速云 閱讀:123 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“join on和where執(zhí)行順序是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“join on和where執(zhí)行順序是什么”吧!

    join on和where執(zhí)行順序

    1、join中相比where優(yōu)先推薦on

    WHERE子句中使用的連接語句,在數(shù)據(jù)庫語言中,被稱為隱性連接。INNER JOIN……ON子句產(chǎn)生的連接稱為顯性連接。(其他JOIN參數(shù)也是顯性連接)WHERE和INNER JOIN產(chǎn)生的連接關(guān)系,沒有本質(zhì)區(qū)別,結(jié)果也一樣。但是!隱性連接隨著數(shù)據(jù)庫語言的規(guī)范和發(fā)展,已經(jīng)逐漸被淘汰,比較新的數(shù)據(jù)庫語言基本上已經(jīng)拋棄了隱性連接,全部采用顯性連接了。

    2. 邏輯上一個query的執(zhí)行順序(不是實(shí)際) 

    1. FROM 
    2. ON 
    3. JOIN 
    4. WHERE 
    5. GROUP BY 
    6. WITH CUBE or WITH ROLLUP 
    7. HAVING 
    8. SELECT 
    9. DISTINCT 
    10. ORDER BY 
    11. TOP 
    說是“邏輯上” 順序,因?yàn)閷?shí)際執(zhí)行時還要看索引,數(shù)據(jù)分布等,看最終優(yōu)化器如何處理,最真實(shí)的順序肯定是執(zhí)行計(jì)劃展示的順序。

    SQL語句中join連表時on和where后都可以跟條件,那么對查詢結(jié)果集,執(zhí)行順序,效率是如何呢? 通過查詢資料發(fā)現(xiàn): 
    區(qū)別: 
    on是對中間結(jié)果進(jìn)行篩選,where是對最終結(jié)果篩選。 

    執(zhí)行順序: 
    先進(jìn)行on的過濾, 而后才進(jìn)行join。 

    效率: 
    如果是inner join, 放on和放where產(chǎn)生的結(jié)果一樣, 但沒說哪個效率速度更高? 如果有outer join (left or right), 就有區(qū)別了, 因?yàn)閛n生效在先, 已經(jīng)提前過濾了一部分?jǐn)?shù)據(jù), 而where生效在后. 
    最后來了解下T-SQL對查詢邏輯處理。 
    T-SQL邏輯查詢的各個階段(編號代表順序): 
    (5)SELECT DISTINCT TOP(<top_specification>) <select_list>                      
    (1)FROM <left_table> <join_type> JOIN <right_table> ON <on_predicate> 
    (2)WHERE <where_predicate> 
    (3)GROUP BY <group_by_specification> 
    (4)HAVING <having_predicate> 
    (6)ORDER BY <order_by_list> 

    T-SQL在查詢各個階級分別干了什么: 
    (1)FROM 階段 
        FROM階段標(biāo)識出查詢的來源表,并處理表運(yùn)算符。在涉及到聯(lián)接運(yùn)算的查詢中(各種join),主要有以下幾個步驟: 
      a.求笛卡爾積。不論是什么類型的聯(lián)接運(yùn)算,首先都是執(zhí)行交叉連接(cross join),求笛卡兒積,生成虛擬表VT1-J1。 

          b.ON篩選器。這個階段對上個步驟生成的VT1-J1進(jìn)行篩選,根據(jù)ON子句中出現(xiàn)的謂詞進(jìn)行篩選,讓謂詞取值為true的行通過了考驗(yàn),插入到VT1-J2。 

         c.添加外部行。如果指定了outer join,還需要將VT1-J2中沒有找到匹配的行,作為外部行添加到VT1-J2中,生成VT1-J3。 

        經(jīng)過以上步驟,F(xiàn)ROM階段就完成了。概括地講,F(xiàn)ROM階段就是進(jìn)行預(yù)處理的,根據(jù)提供的運(yùn)算符對語句中提到的各個表進(jìn)行處理(除了join,還有apply,pivot,unpivot) 

    (2)WHERE階段 
         WHERE階段是根據(jù)<where_predicate>中條件對VT1中的行進(jìn)行篩選,讓條件成立的行才會插入到VT2中。 

    (3)GROUP BY階段 
          GROUP階段按照指定的列名列表,將VT2中的行進(jìn)行分組,生成VT3。最后每個分組只有一行。 

    (4)HAVING階段 
          該階段根據(jù)HAVING子句中出現(xiàn)的謂詞對VT3的分組進(jìn)行篩選,并將符合條件的組插入到VT4中。 

    (5)SELECT階段 
      這個階段是投影的過程,處理SELECT子句提到的元素,產(chǎn)生VT5。這個步驟一般按下列順序進(jìn)行 
            a.計(jì)算SELECT列表中的表達(dá)式,生成VT5-1。 
            b.若有DISTINCT,則刪除VT5-1中的重復(fù)行,生成VT5-2 
            c.若有TOP,則根據(jù)ORDER BY子句定義的邏輯順序,從VT5-2中選擇簽名指定數(shù)量或者百分比的行,生成VT5-3 

    (6)ORDER BY階段 
         根據(jù)ORDER BY子句中指定的列明列表,對VT5-3中的行,進(jìn)行排序,生成游標(biāo)VC6.

    如果是inner join, 放on和放where產(chǎn)生的結(jié)果一樣, 執(zhí)行計(jì)劃也是一樣,但推薦使用on。但如果有outer join (left or right), 就有區(qū)別了, 因?yàn)閛n生效在先, 已經(jīng)提前過濾了一部分?jǐn)?shù)據(jù), 而where生效在后,而且on對于outer join有不生效的情況,需要看and條件是作用在左表還是右表。

    擴(kuò)展:SQL執(zhí)行順序join在where前面

    • 取a表和b表join的數(shù)據(jù)sql

    原本意圖是取a表的昨日分區(qū)數(shù)據(jù)和b表的昨日分區(qū)數(shù)據(jù)進(jìn)行join,但是發(fā)現(xiàn)加上and b.dt = '${daily}'的條件后就取不到在a表中存在的數(shù)據(jù)了

    select substr(a.create_time,1,7) create_month,a.service_id,a.unit_number,a.company_name,coalesce(b.unified_social_credit_code,'unknown') unified_social_credit_code
    ,a.company_id,b.company_id as company_id_b,a.dt,b.dt
    from clouduser.dz_company a 
    left join clouduser.dz_company_detail b on a.company_id = b.company_id
    where a.dt = '${daily}' 
    --and b.dt = '${daily}'
    and substr(a.create_time,1,7) = '2022-09'
    and a.company_name = '浙江港都電子有限公司';

    運(yùn)行結(jié)果

    join?on和where執(zhí)行順序是什么

    • 原因是where執(zhí)行是在join之后,join出來的臨時表中,由于在b表中沒有匹配到數(shù)據(jù),所以b.dt為null,這時候執(zhí)行where b.dt = '${daily}'的條件篩選不到這條數(shù)據(jù)。

    • 優(yōu)化方法

    現(xiàn)在子查詢中將b表的昨日分區(qū)查詢出來,再和a表join

    with
    r1 as (select * from clouduser.dz_company_detail where dt = '2022-10-17'),
    r2 as (
    select substr(a.create_time,1,7) create_month,a.service_id,a.unit_number,a.company_name,coalesce(b.unified_social_credit_code,'unknown') unified_social_credit_code
    ,a.company_id,b.company_id as company_id_b
    from clouduser.dz_company a 
    left join r1 b on a.company_id = b.company_id
    where a.dt = '${daily}' 
    --and b.dt = '${daily}'
    and substr(a.create_time,1,7) = '2022-09'
    and a.company_name = '浙江港都電子有限公司'
    )
    select * from r2;

    執(zhí)行結(jié)果

    join?on和where執(zhí)行順序是什么

    可以看到正常查詢出a表中的數(shù)據(jù)了

    感謝各位的閱讀,以上就是“join on和where執(zhí)行順序是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對join on和where執(zhí)行順序是什么這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI