在MySQL數據庫中,聚合函數(Aggregate Function)是一類返回單個結果的函數,它們從一組值中計算出一個結果。常見的聚合函數包括COUNT、SUM、AVG、MAX、MIN等。當需要對表中的數據進行聚合統計時,可以利用聚合函數來實現。onlyfullgroupby函數是 MySQL 5.7 新增的函數,為解決在使用GROUP BY分組聚合操作時省略掉的非聚合列帶來的影響而設計的。
一、onlyfullgroupby函數介紹
在 MySQL 中,當我們使用 GROUP BY 對數據進行分組聚合時,查詢語句中的 SELECT 語句中的非聚合列必須要出現在 GROUP BY 語句中。只有這樣,MySQL 才能對每個分組進行聚合操作,否則就會出現錯誤。但是,在實際查詢過程中,可能需要查詢的列中還包含了非聚合列,而且這個非聚合列在 GROUP BY 子句中並不需要出現,那麼這時候就需要用到 onlyfullgroupby 函數。
onlyfullgroupby 函數是 MySQL 5.7 新增的函數,用於解決在 GROUP BY 子句中只列出一部分非聚合列而省略了另一部分非聚合列所可能引起的問題。這個函數可以為遺漏的非聚合列提供隱式的 GROUP BY 處理。只要查詢 SELECT 列表中所有非聚合列也都是函數依賴於 GROUP BY 子句中的列(即:所有被查詢的非聚合列都能夠被 GROUP BY 子句中的列唯一確定),那麼 MySQL 會給這些列自動添加 GROUP BY 子句。
如下是一個示例查詢語句: SELECT a, b, MAX(c) FROM tbl GROUP BY a; 顯然,上述查詢語句可能出錯,因為b列沒有被包含在GROUP BY子句中,並且在SELECT列表中是非聚合列,這種問題在MySQL 5.7之前,開發者也是需要手動解決,例如,通過使用b字段替換掉MAX(c): SELECT a, b, MAX(c) FROM tbl GROUP BY a, b; 然而,如果使用MySQL 5.7及以上版本,並且使用了onlyfullgroupby函數,則可以避免手動處理的麻煩: SELECT a, b, MAX(c) FROM tbl GROUP BY a, onlyfullgroupby(b); 這裡使用了 onlyfullgroupby 函數來規避未包含在 GROUP BY 子句中的列 b,讓GROUP BY 子句隱含包含了這個列。
二、onlyfullgroupby函數的使用場景
onlyfullgroupby 函數的使用場景包括以下兩種情況:
1. 查詢語句包含聚合函數和非聚合列
當在查詢語句中包含聚合函數和非聚合列時,通常需要用 GROUP BY 語句對查詢結果進行分組,只有這樣才能保證返回結果的正確性。如果查詢語句中未包括所有非聚合列,結果集將會出現錯誤。此時可以使用 onlyfullgroupby 函數,來規避未包含在 GROUP BY 子句中的非聚合列。
2. 查詢語句使用了窗口函數
當在查詢語句中使用窗口函數時,例如 ROW_NUMBER(),通常情況下不需要使用 GROUP BY 子句進行分組。但是,如果窗口函數需要統計非聚合列的信息,那麼 GROUP BY 子句就需要用到了。此時可以使用 onlyfullgroupby 函數,來自動補充未包含在 GROUP BY 子句中的非聚合列。
三、onlyfullgroupby函數使用舉例
下面通過幾個實際的例子來說明 onlyfullgroupby 函數的使用。
1. 查詢分組數據中的最新一條數據
假設我們需要查詢一個論壇網站上用戶最新發表的一條帖子:
SELECT u.id, u.name, t.title, MAX(t.post_time) last_post_time FROM user u, topic t WHERE u.id = t.author_id GROUP BY u.id;
上面的查詢語句中,我們通過 GROUP BY 子句對用戶進行分組,然後通過 MAX 函數來找到每個用戶最新的發表時間。
如果不使用 onlyfullgroupby 函數,MySQL 將無法判斷查詢語句中的 title 列屬於哪個帖子,因此會報錯。因此,我們需要使用 onlyfullgroupby 函數來告訴 MySQL,title 列也是需要分組的。
SELECT u.id, u.name, t.title, MAX(t.post_time) last_post_time FROM user u, topic t WHERE u.id = t.author_id GROUP BY u.id, onlyfullgroupby(t.title);
2. 查詢商品售出數量排名前 N 的分類
假設我們有一個訂單表 order 表和一個商品表 item 表,現在需要查詢出售出數量最多的前 N 個分類:
SELECT item.category, COUNT(order.id) order_count FROM order, item WHERE order.item_id = item.id GROUP BY item.category ORDER BY order_count DESC LIMIT 10;
上面的代碼會報錯,因為查詢語句中只包含了 item.category 列,而未包含 order_count 列,如果不加處理會得到以下錯誤提示:
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.order.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
我們可以使用 onlyfullgroupby 函數,讓 MySQL 自動將 order_count 列加入到 GROUP BY 子句中:
SELECT item.category, COUNT(order.id) order_count FROM order, item WHERE order.item_id = item.id GROUP BY item.category, onlyfullgroupby(order_count) ORDER BY order_count DESC LIMIT 10;
四、總結
onlyfullgroupby 函數可以解決在使用 GROUP BY 分組聚合操作時省略掉的非聚合列帶來的影響。只要查詢 SELECT 列表中所有非聚合列也都是函數依賴於 GROUP BY 子句中的列,那麼 MySQL 會給這些列自動添加 GROUP BY 子句。在實際使用過程中,需要注意 onlyfullgroupby 函數的使用場景,以及避免出現 GROUP BY 子句的錯誤。通過本文的講解,相信讀者對 onlyfullgroupby 函數的用法已經有了一定的了解。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/271384.html