
總第168篇/張俊紅
寫過 Sql 的同學應該都知道 group by 是用來對資料進行分組的,一般與聚合函數一起使用,對分組後的資料進行聚合。雖然大家都在用,但是有些同學還是不太清楚 group by 的底層到底是如何實作分組并且最後進行聚合的。今天就講講 group by 的底層實作。
我們直接來看例子,下面有一張表 t,存儲了不同日期對應的不同品類的銷量,具體資料如下:
現在我們要統計2019年1月1到1月3期間沒每個品類的總銷量,這個需求我們就可以用 group by 來實作,實作代碼如下:
select cat ,sum(sales)
from
t
where sale_date between "2019/1/1" and "2019/1/3"
group by cat
複制
上面代碼中的 group by 具體執行過程是什麼樣子的呢?我們看一下下面這這張圖。
通過上圖我們可以看出 group by 會對所有的資料先根據 cat 字段進行分組,然後針對分組後的資料在組内進行聚合運算(計數、求和、求均值等),最後再将聚合後的每組資料進行彙總就得到了我們想要的結果。在上圖中大家應該看到了分組子產品隻有 cat 這一列是标紅加粗,sale_date 和 sales 這兩列是比較虛的字型,為什麼會這樣呢?難道我寫錯了?其實不然,是我故意的。為什麼要故意呢?我們看一下下面這張圖:
上圖是将表 t 在 Excel 中做一個資料透視表,如果我們隻将 cat 這一列拖到行區域的時候,在表中隻顯示出了 cat 這一列,别的列是沒有顯示出來的,Sql 中也是一樣的道理,是以我們隻有 cat 列是标紅加粗顯示,而其他列是虛的,是因為其他列在這個階段是沒有顯示出來,不過他們也是随時待命的狀态。
一旦你指明了要按照哪列資料進行聚合,他們就會按照事先分好的組對要聚合的列去進行相應的聚合運算,然後将結果進行彙總,就是我們想要的資料了。
上面的是最簡單的一個例子,就是隻按照 cat 這一列進行分組,如果我們現在想要同時對 cat 和 sale_date 這兩列來進行分組的話該怎麼實作呢?實作代碼如下:
select
cat
,sale_date
,sum(sales)
from
t
where sale_date between "2019/1/1" and "2019/1/3"
group by cat,sale_date
複制
這個時候就相當于在透視表裡面把 cat 和 sale_date 同時拖到了行區域,但是也是隻顯示這兩列,而别的列是不顯示的,隻有指明了聚合列的時候,才會把聚合後的結果展示出來。
單純的分組聚合的原理大家應該都明白了,不過這裡有一個特别需要注意的點不知道大家有沒有注意到,就是除了聚合列以外,select 後面要查詢的列,必須在 group by 的後面出現。為什麼要這樣呢?通過上面的兩個例子,我們也看到了,雖然一個資料表會有多列,但是在 group by 的時候,隻會顯示出來你 group by 的列,而其他列是不顯示出來的,沒有顯示出來的列,你在 select 的時候肯定是查詢不到的。