⑴ sql 之 ON 和 WHERE執行順序
那麼 WHERE 是不是一定是在 ON 之後生效了 ? 我們帶著這個疑問往下看
on 針對的關聯條件,是表與表之間通過哪些列、以什麼條件進行關聯,而 where 針對的是過濾條件;兩者從概念上來講是不同的
另外 on 一定是與 join 一並使用的,join 會添加外部行,並將外部行中被驅動表的欄位填充 null ,而 where 進行過濾的時候,只有邏輯判斷為 true 的記錄才會保留,邏輯值為 false 和 unknown 的記錄都會過濾掉;兩者得到的結果會有所不同。
上面說的可能有些抽象,我們結合具體示例來看;MySQL 版本 5.7.21 ,准備表和初始數據
我們先來看看 left join(right join類似)
我們可以看到:
我們再來看看 inner join
我們可以看到,執行結果是一樣的,inner join 查詢的就是驅動表與被驅動表同時存在的記錄,所以過濾條件不管放在 ON 里,還是放在 WHERE 里,執行結果是一樣的
ON 和 WHERE 的生效時機
ON 後的關聯條件與 WHERE 後的過濾條件,這兩者的執行順序是否如 SQL 執行順序圖中說的那樣,ON 一定先與 WHERE ?
問題先放著,我們以 left join 為例,來看看 4 個案例,也許從中能找到我們想要的答案
1、左表與右表都沒二級索引
剛好上面的 tbl_a 和 tbl_b 滿足條件,我們來看看 SQL 的執行計劃
驅動表是 tbl_a,這個相信大家沒問題,我們重點看下 type 和 Extra
這條 SQL 的執行流程應該是這樣的:
此時大家看出什麼了沒 ? ON 後的關聯條件是在 WHERE 後的過濾條件之前生效的嗎 ?
這個案例不太常見,因為表沒有二級索引,我們接著往下看看有二級索引的情況
2、左表有二級索引,右表無二級索引
我們在 tbl_a 建一個組合索引 create index idx_bcd on tbl_a(b, c, d); ,然後往 tbl_a 和 tbl_b 中各插入 10W 條記錄,我們再來看執行計劃
此時 WHERE 後的過濾條件的生效時機也是早於 ON 後的關聯條件的。
3、左表無二級索引,右表有二級索引
將 tbl_b 作為左表,tbl_a 作為右表,我們來看效果
4、左表與右表都有二級索引
我們在 tbl_b 表上建一個組合索引 create index idx_bcd on tbl_b(b, c, d); 我們來看看 SQL 的執行計劃
自此,關於 ON 和 WHERE 的生效時機,你清楚了嗎 ?
他兩的生效時機,需要結合表結構,以及具體的 SQL 來分析,而不是 ON 一定先於 WHERE
⑵ 大數據開發工程師Hive(Hive Sql的執行順序)
Hive中SQL的執行順序:
(1) from :對from左邊的表和右邊的表計算笛卡爾積,產生虛表VT1;
(2) on : 對虛表VT1進行on過濾,只有那些符合 的行才會被記錄在虛表VT2中;
(3) join :如果指定了outer join(比如left join、 right join),那麼保留表中未匹配的行就會作為外部行添加到虛擬表VT2中,產生虛擬表VT3;
(4) where :對虛擬表VT3進行where條件過濾。只有符合 的記錄才會被插入到虛擬表VT4中;
(5) group by :根據group by子句中的列,對VT4中的記錄進行分組操作,產生VT5;
(6) having : 對虛擬表VT5應用having過濾,只有符合 的記錄才會被 插入到虛擬表VT6中;
(7) select :執行select操作,選擇指定的列,插入到虛擬表VT7中;
(8) distinct :對VT7中的記錄進行去重。產生虛擬表VT8;
(9) order :將虛擬表VT8中的記錄按照 進行排序操作,產生虛擬表VT9;
(10) limit :取出指定行的記錄,產生虛擬表VT10, 並將結果返回;
partition by 通常會用於和開窗及分析函數一起使用,partition by是在select執行完 後 的結果集上進行的;
(每日1小題,進步1點點)
⑶ sql執行順序以及on和where的區別
(1.)select語句的執行順序
Processing Order of the SELECT statement
The following steps show the processing order for a SELECT statement.
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
(5)SELECT DISTINCT
(7)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階段標識出查詢的來源表,並處理表運算符。在涉及到聯接運算的查詢中(各種join),主要有以下幾個步驟:
a.求笛卡爾積。不論是什麼類型的聯接運算,首先都是執行交叉連接(cross join),求笛卡兒積,生成虛擬表VT1-J1。
b.ON篩選器。這個階段對上個步驟生成的VT1-J1進行篩選,根據ON子句中出現的謂詞進行篩選,讓謂詞取值為true的行通過了考驗,插入到VT1-J2。
c.添加外部行。如果指定了outer join,還需要將VT1-J2中沒有找到匹配的行,作為外部行添加到VT1-J2中,生成VT1-J3。
經過以上步驟,FROM階段就完成了。概括地講,FROM階段就是進行預處理的,根據提供的運算符對語句中提到的各個表進行處理(除了join,還有apply,pivot,unpivot)
(2)WHERE階段
WHERE階段是根據<where_predicate>中條件對VT1中的行進行篩選,讓條件成立的行才會插入到VT2中。
(3)GROUP BY階段
GROUP階段按照指定的列名列表,將VT2中的行進行分組,生成VT3。最後每個分組只有一行。
(4)HAVING階段
該階段根據HAVING子句中出現的謂詞對VT3的分組進行篩選,並將符合條件的組插入到VT4中。
(5)SELECT階段
這個階段是投影的過程,處理SELECT子句提到的元素,產生VT5。這個步驟一般按下列順序進行
a.計算SELECT列表中的表達式,生成VT5-1。
b.若有DISTINCT,則刪除VT5-1中的重復行,生成VT5-2
c.若有TOP,則根據ORDER BY子句定義的邏輯順序,從VT5-2中選擇簽名指定數量或者百分比的行,生成VT5-3
(6)ORDER BY階段
根據ORDER BY子句中指定的列明列表,對VT5-3中的行,進行排序,生成游標VC6.
如果On和where只能選其一的話:
先進行on的過濾, 而後才進行join, 這樣就避免了兩個大表產生全部數據的笛卡爾積的龐大數據.
這些步驟執行時, 每個步驟都會產生一個虛擬表,該虛擬表被用作下一個步驟的輸入。這些虛擬表對調用者(客戶端應用程序或者外部查詢)不可用。只是最後一步生成的表才會返回 給調用者。
如果沒有在查詢中指定某一子句,將跳過相應的步驟。
(2) 那 on 和where 那個更高效呢
如果是inner join, 放on和放where產生的結果一樣, 但沒說哪個效率速度更高? 如果有outer join (left or right), 就有區別了, 因為on生效在先, 已經提前過濾了一部分數據, 而where生效在後.
綜合一下, 感覺還是放在on里更有效率, 因為它先於where執行.
先笛卡爾積, 然後再on過濾, 如果join是inner的, 就繼續往下走, 如果join 是left join, 就把on過濾掉的左主表中的數據再添加回來; 然後再執行where里的過濾;
on中不是最終過濾, 因為後面left join還可能添加回來, 而where才是最終過濾.
只有當使用外連接(left, right)時, on 和 where 才有這個區別, 如果用inner join, 在哪裡制定都一樣, 因為on 之後就是where, 中間沒有其它步驟.
⑷ 關於SQL中join on 的用法神馬的
join on 就是表連接.
select * from table1 as t1 join table2 as t2 on(t1.a= t2.b) where t1.c = x order by t1.d desc;
等價於
select * from table 1 as t1 ,table2 as t2 where t1.a = t2.b and t1.c = x order by t1.d desc;
2個SQL語句對於資料庫來說是一樣的,執行計劃都沒有區別...
你可以試一下.