盤點SQL中幾個比較實用的小 Tips!
1. 前言
大家好,我是安果!
工作中,我們經常需要編寫 SQL 腳本,對數據庫進行增、刪、改、查,很少會考慮到 Sql 性能優化
實際上,從性能角度考慮,有很多 Sql 關鍵字都有它們各自的使用場景;如果使用恰當,能大大地提升后端服務的響應效率
下面以 Mysql 為例,羅列出幾個比較實用的小 Tips
2. union、union all、or
union [all] 代表聯合查詢,即:將多個查詢結果合并起來成一個結果并返回
PS:union 聯合查詢針對每一個查詢結果,必須保證列數量、列數據類型及查詢順序一致
語法如下:
- # 以兩張表的聯合查詢為例
- # table_one:表一
- # table_two:表二
- # 表一中的查詢字段:table_one_field1,table_one_fileld2...
- # 表二種的查詢字段:table_two_field1,table_two_field2...
- # 注意:表一、表二查詢字段數目、字段類型、字段順序應該保持一致
- select table_one_field1,table_one_fileld2...
- from table_one
- union [all]
- select table_two_field1,table_two_field2...
- from table_two;
其中,union、union all、or 三者的區別如下:
-
union
表鏈接后會利用字段的順序進行排序,以此篩選掉重復的數據行,最后再返回結果
因此,當數據量很大時效率很低
-
union all
相比 union,union all 在表鏈接時不會刪除重復的數據行,直接返回表聯合后的結果
因此,union all 執行效率要高很多,在不需要去重和排序時,更推薦使用 union all
-
or
or 用于 SQL where 子句中,SQL 腳本可讀性更高,但是它會引起全表掃描,根本不走索引查詢
所以通常情況下,union [all] 查詢會利用索引進行查詢,執行效率要高于 or;但是當 or 條件中查詢列相同,or 的執行效率要高于 union
3. group by + having、where
group by 分組查詢,根據一個或多個列對結果集進行分組,一般配合聚合函數使用
語法如下:
- # 查詢字段:多個查詢字段
- select 查詢字段...,聚合函數...
- from table_one where 條件語句 group by 分組字段...having 分組條件;
- # 比如
- select red_num1,count(red_num1)
- from dlt where create_at>='2021-11-01' group by red_num1;
其中,having 和 where 使用上有下面區別:
-
where
在 group by 分組前執行,將查詢結果按照條件過濾數據
需要注意的是,where 無法與聚合函數一起使用
-
having
只能配合 group by 使用,在分組之后執行,用于過濾滿足條件的組
需要注意的是,分組是一個耗時的操作,建議在分組前使用 where 對數據進行一次過濾,然后再進行分組
比如,where 搭配 having 一起使用
- # 查詢表dlt
- # 首先,使用where通過時間過濾數據
- # 然后,使用字段red_num1+group by對數據進行分組
- # 最后,使用having對分組后的數據再進行一次過濾
- select red_num1,count(red_num1)
- from dlt where create_at>='2021-10-01' group by red_num1 having count(red_num1)>=2;
4. exists、in
exists 用于 where 子句中,一般用于判斷子查詢中是否會返回數據,如果返回的數據不為空,則為 True,否則為 False
PS:exists 也可以搭配 not 使用,查詢出不滿足子查詢語句的數據
語法如下:
- -- exists使用
- select *
- from 表一 where exists(select * from 表二 where 條件判斷語句);
- -- not exists使用
- select *
- from 表一 where not exists(select * from 表二 where 條件判斷語句);
in 同樣用于 where 子句中,篩選出某個表字段存在于多個值中的所有數據
關鍵字 in 常見的 2 種使用方式如下:
- -- in 使用
- -- 方式一
- select *
- from 表名 where 字段 in(過濾字段1,過濾字段2,過濾字段3...);
- -- 方式二
- select *
- from 表名1
- where 字段1 in (select 字段2 from 表名2 where condition)
由于 SQL 做子查詢最優方案是小表驅動大表,對于 in 來說是子查詢表驅動外表,當子查詢表數據少于主表數據時推薦使用
而 exists 是外表驅動子查詢表,因此當外表數據少于子查詢表時更推薦使用