在 MySQL 中,GROUP?BY用于將具有指定列中相同值的行分組在一起,允許對數(shù)據(jù)進(jìn)行分類和聚合,即按照指定的字段或者表達(dá)式進(jìn)行分組。
我們現(xiàn)在有一個(gè)簡單的表student,內(nèi)容如下表1所示:
對于上面這個(gè)表,我們要求查詢每個(gè)班幾個(gè)人?
答案是:select class,count(class) from student group by class;
有很多初學(xué)者在學(xué)習(xí)group by時(shí),不明白為什么不是select * from student ?group by ?class,為什么一定不能是*,而是某一個(gè)列或者某個(gè)列的聚合函數(shù),group by 應(yīng)該怎么去理解呢?
上表如果執(zhí)行 select name from class;語句,應(yīng)該很好理解,展示如下表2內(nèi)容:
為了能夠更好的理解“group by”多個(gè)列“和”聚合函數(shù)“的應(yīng)用,我們在思考的過程中,由表1到表2的過程中,增加一個(gè)虛構(gòu)的中間表:虛擬表3。下面說說如何思考上面SQL語句執(zhí)行情況:
1.from ?student:該句執(zhí)行后,應(yīng)該結(jié)果和表1一樣,就是原來的student表。
2.from ?student ?group ?by ??class:該句執(zhí)行后,生成過程是這樣的:group ?by ?class,那么找class那一列,具有相同class值的行,合并成一行,我們想象生成了虛擬表3,如下所圖所示。如對于class值為”一班” 的,那么id為1,3,4的三行合并成1行,即所有的id值,name值和class值寫到一行里面,同樣,對于class值為”二班”的,那么id為2,3的二行合并成一行,所有的id值,name值和class值寫到一行里面。
3.接下來就要針對虛擬表3執(zhí)行Select語句了:
(1)如果執(zhí)行select *的話,那么返回的結(jié)果應(yīng)該是虛擬表3,可是id和name中有的單元格里面的內(nèi)容是多個(gè)值,而關(guān)系數(shù)據(jù)庫就是基于關(guān)系的,一個(gè)單元格中是不允許有多個(gè)值的,所以執(zhí)行select * 語句就報(bào)錯(cuò)了。
(2)我們再看class列,每個(gè)單元格只有一個(gè)數(shù)據(jù),所以我們select class的話,就沒有問題了。為什么class列每個(gè)單元格只有一個(gè)值呢?因?yàn)槲覀兙褪怯胏lass列來group by的。
(3)那么對于id和name里面的單元格有多個(gè)數(shù)據(jù)的情況怎么辦呢?答案就是使用聚合函數(shù),聚合函數(shù)就用來輸入多個(gè)數(shù)據(jù),輸出一個(gè)數(shù)據(jù)的。如count(class)等聚合函數(shù),而每個(gè)聚合函數(shù)的輸入就是每一個(gè)多數(shù)據(jù)的單元格。
4、所以,我們執(zhí)行select ?class, count(class) ?from ?student ?group ?by ?class;,那么count(class)就對虛擬表3的class列的每個(gè)單元格進(jìn)行count操作,最后執(zhí)行結(jié)果如下:
所以,通過上面的分析,如果對多個(gè)字段進(jìn)行分組,原理也是一樣的。
Copyright ? 2013-2021 河南云和數(shù)據(jù)信息技術(shù)有限公司 豫ICP備14003305號 ISP經(jīng)營許可證:豫B-20160281