在很多場景時,需要對數據按照某條件進行分組統計其數量、平均值等等。有這種需求,SQL自然也有解決方式。
在SQL中通過group by子句對結果按某條件進行分組。語法:
select count(column1), columnJ from table_name group by columnJ;
group by是后接檢索的列或者表達式。表示對該列或者表達式的數據進行分組,該列上或者表達式相同的數據放在同一組。
group by使用的注意點:
- group by必須作用在檢索列上或者表達式上
- group by可以作用在多個列上,會按照列的順序,進行逐層分組
- group by后的列是select的子句中的檢索列或者表達式
- group by會將列為NULL值的作為一組
注:大多數情況的場景都是使用group by進行分組,然后對分組的數據進行聚合統計。很少是分組后取某組中的個別列的數據。如:
select name, age from teacher group by age;
select子句中包含了非聚合的列name(這屬於取分組結果中個別列的數據情況)。
在Mysql中默認模式:ONLY_FULL_GROUP_BY下,如果執行以上SQL會報錯;可以將其關閉,如果再執行以上SQL,mysql將會取分組中的每組的第一行數據作為結果集。
通過看下面的示例,來熟悉下group by:
select age, count(name) as group_count from teacher group by age;
以上的SQL表示的含義:按年齡分組統計每個年齡的老師數量,執行結果:
age | group_count |
---|---|
25 | 2 |
26 | 2 |
27 | 1 |
28 | 1 |
29 | 1 |
再來看一個例子:
select name, max(age), min(age) from person group by name;
以上SQL表示,按照姓名分組統計,找出每組中最大年齡,最小年齡的人,執行結果如下
name | max | min |
---|---|---|
xiaohei | 20 | 29 |
xiaohong | 28 | 26 |
xiaolan | 67 | 56 |
以上的例子足以理解group by。group by即對結果集進行按條件進行分組,然后常進行聚合處理。
但是往往仍需要對分組后的結果進行過濾處理,SQL中使用另外一個子句HAVING對group by的分組結果進行過濾處理,如下:
select age, count(name) as group_count from teacher group by age having age < 27;
執行結果
age | count |
---|---|
25 | 2 |
26 | 2 |
對分組結果進行過濾,只檢索出分組中年齡小於27的組。
在看到having時,不免聯系到where子句,下面總結下他們的異同點:
相同點 | 1.having和where都是對結果按照條件過濾; 2.在使用where的地方都可以使用having(不常用); |
---|---|
不同點 | 1.針對的過濾數據不一樣,having主要是用來過濾分組,where主要是過濾表中數據行; 2.having和where子句的位置不一樣,having在group by后,where在from子句后; 3.having通常配合group by使用; |
那么在有having過濾情況下是否還能使用where呢?
根據上表中不同點1可以看出,是可以的。where是對數據行過濾,然后再對過濾后的行進行分組,再對分組進行having過濾。
下表列出了SQL的執行順序:
子句 | 說明 | 使用場景 |
---|---|---|
select | 查詢數據 | 在db數據檢索時使用 |
from | 檢索的表 | 檢索時使用 |
where | 過濾數據的條件 | 需要對數據進行篩選時 |
gropu by | 分組select的結果集 | 需要聚合統計時常用 |
having | 過濾分組 | 對分組進行過濾時需要 |
order by | 排序結果集 | 需要按照某種順序展示數據 |
參考
《SQL必知必會》