MySQL 聚合函數(一)聚合(組合)函數概述


  MySQL版本:5.7+

  本節介紹對值的集合進行操作的組合(聚合)函數。翻譯自:Aggregate (GROUP BY) Function Descriptions

一、MySQL 5.7中的聚合函數

  MySQL 5.7中的聚合函數如下:

  除非另有說明,否則組合函數會忽略NULL值。

  如果在不包含Group By子句的語句中使用組合函數,就等效於對所有行進行分組。(個人理解是,結果總是只有一行。)關於這點的更多信息,后面的小節“MySQL處理Group By的方式”會講到。

  聚合函數中,方差和標准差函數會對數值參數返回DOUBLE值。SUM()和AVG()對精確值參數(integer或DECIMAL)返回DECIMAL值,而對近似值參數(FLOAT或DOUBLE)返回DOUBLE值。

  時間類型的參數對SUM()和AVG()無效。它們會把時間類型的值轉換成數字,丟棄第一個非數字字符后的所有信息)。如果要解決這個問題,先要將時間類型的值轉換為合適的數值單元,在執行聚合操作后,再轉換回時間值。如下所示:

SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col))) FROM tbl_name;
SELECT FROM_DAYS(SUM(TO_DAYS(date_col))) FROM tbl_name;

  諸如SUM()和AVG()這樣需要數值參數的函數,會對非數值參數做必要的強制轉換。而對於SET或ENUM值,強制轉換操作會導致使用基礎數值。

  BIT_AND(),BIT_OR()和BIT_XOR()聚合函數執行位操作。它們需要BIGINT(64位整數)參數並返回BIGINT值。其他類型的參數將轉換為BIGINT並可能發生截斷。而在MySQL 8.0中,允許位操作采用二進制字符串類型參數(BINARY,VARBINARY和BLOB類型),詳見其手冊的12.12節。

 

二、聚合函數詳解

  2.1 AVG()

AVG([DISTINCT] expr)

  函數返回expr的平均值。

  DISTINCT則用於返回expr的不同值的平均值。

  如果沒有匹配的行,AVG()返回null。

 

  2.2 COUNT()

COUNT(expr)

  返回SELECT語句檢索的行中expr的非NULL值的計數。

  返回結果是BIGINT值。

  如果沒有匹配的行,count()返回0.

  

  count(*)有些不同,它返回取回的行的行數的計數,無論它們是否包含NULL值。

  對於諸如InnoDB之類的事務存儲引擎,存儲精確的行數是有問題的。多個事務可能同時發生,每個事務都可能影響計數。

  所以InnoDB不在內部保留表的行數,因為並發事務可能同時“看到”不同數量的行。因此,SELECT COUNT(*)語句只計算當前事務可見的行。

  在MySQL 5.7.18之前,InnoDB通過掃描聚集索引(clustered index)來處理SELECT COUNT(*)語句。從MySQL 5.7.18開始,InnoDB通過遍歷最小的可用二級索引來處理SELECT COUNT(*)語句,除非索引或優化器提示指示優化器使用不同的索引。如果不存在輔助索引,則掃描聚集索引。

  如果索引記錄不完全在緩沖池中,那么處理select count(*)語句需要一些時間。為了更快地計算,可以創建一個計數表,讓應用程序根據插入和刪除操作更新它。但是,在數千個並發事務正在啟動對同一計數器表的更新的情況下,此方法可能無法很好地擴展。因此,如果大概的行數可以滿足需求,請使用SHOW TABLE STATUS。

  對於MyISAM表,如果SELECT從一個表沒有檢索到其他列,並且沒有WHERE子句,而只返回COUNT(*)的結果,則COUNT(*)會被優化,可以快速返回。例如:

 SELECT COUNT(*) FROM student;

  此優化僅適用於MyISAM表,因為為此存儲引擎存儲了精確的行數,並且可以非常快速地訪問。COUNT(1)則僅在第一列定義為NULL時,受到相同額度優化。

 

  2.3 COUNT(DISTINCT ...)

COUNT(DISTINCT expr,[expr...])

  函數返回返回不相同且非NULL的expr值的行數。

  如果沒有匹配的行,則COUNT(DISTINCT)返回0。

  在MySQL中,您可以通過提供表達式列表,來獲取不包含NULL的不同表達式組合的數量。而在標准表達式中,必須在COUNT(DISTINCT ...)中對所有表達式進行連接。

 

  2.4 GROUP_CONCAT()

GROUP_CONCAT([DISTINCT] expr [,expr ...]
             [ORDER BY {unsigned_integer | col_name | expr}
                 [ASC | DESC] [,col_name ...]]
             [SEPARATOR str_val])

  這個函數把來自同一個組的某一列(或者多列)的數據連接起來成為一個字符串。

  如果沒有非NULL值,返回NULL。

  示例如下:

/*001*/
/*成績表中只對學生ID分組*/
select SId, group_concat(cId),group_concat(score) from sc group by SId;

  結果如下,並沒有排序

/*002*/
/*排序后連接,改變分隔符*/
select SId, group_concat(cId),group_concat(score order by score desc separator '  ') 
from sc group by SId;

  結果如下:

  至於對多個expr的連接,試了試,會把兩個字段無縫連在一起。

select SId, group_concat(cId,score),group_concat(score) from sc group by SId;

 

  Group_Concat()的結果將截斷為group_concat_max_len系統變量所設置的最大長度,該變量的默認值為1024。

  而返回值是非二進制或二進制字符串,具體取決於參數是非二進制還是二進制字符串。

  返回的結果類型為TEXT或BLOB,除非group_concat_max_len小於或等於512,這種情況下,結果類型為VARCHAR或VARBINARY。

 

  2.5 JSON_ARRAYAGG(col or expr)

  將結果集聚合為單個JSON數組,其元素由參數列的值組成。此數組中元素的順序未定義。該函數作用於計算為單個值的列或表達式。

  異常返回NULL。

  示例如下:

 

  2.6 JSON_OBJECTAGG(key,value)

  兩個列名或表達式作為參數,第一個用作鍵,第二個用作值,並返回包含鍵值對的JSON對象。

  如果結果不包含任何行,或者出現錯誤,則返回NULL。如果任何鍵名稱為NULL或參數數量不等於2,則會發生錯誤。

 

  如何處理重復key,參考原文此處。

 

  2.7 其余函數

  位函數進行位操作。

  標准差和方差函數,為了兼容有不同的函數名。

  詳見原文檔。

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM