MySQL?count()聚合函數(shù)詳解
深入剖析一下 MySQL 中的 COUNT() 函數(shù)。它是 SQL 中最常用的聚合函數(shù)之一,用于計算表中符合特定條件的行數(shù)。
核心功能
COUNT() 函數(shù)的核心功能是計數(shù)。它可以用來:
統(tǒng)計表中所有行的總數(shù)。
統(tǒng)計表中特定列的非 NULL 值的數(shù)量。
結合
WHERE子句,統(tǒng)計滿足特定條件的行的數(shù)量。結合
GROUP BY子句,統(tǒng)計每個分組中的行數(shù)。
語法形式
COUNT() 函數(shù)主要有三種語法形式,它們在行為和性能上有所不同:
COUNT(*)
功能: 統(tǒng)計查詢結果集中的總行數(shù)。
計數(shù)方式: 它計算所有行,不管該行中的列是否包含 NULL 值。即使整行所有列都是 NULL,
COUNT(*)也會將其計入。性能: 在大多數(shù)現(xiàn)代 MySQL 版本(尤其是 InnoDB 存儲引擎)中,
COUNT(*)通常經(jīng)過高度優(yōu)化。MySQL 知道COUNT(*)只需要行數(shù),而不需要檢查任何具體的列值。這是獲取表總行數(shù)或分組行數(shù)的推薦方式。示例:
-- 統(tǒng)計 `users` 表中的總用戶數(shù) SELECT COUNT(*) FROM users; -- 統(tǒng)計每個部門 (`dept_id`) 的員工數(shù)量 SELECT dept_id, COUNT(*) AS employee_count FROM employees GROUP BY dept_id;
COUNT(expression)功能: 統(tǒng)計表達式
expression計算結果為非 NULL 值的行數(shù)。計數(shù)方式: 對每一行計算給定的表達式 (
expression)。如果表達式的結果是 非 NULL,則計數(shù)加 1;如果結果是 NULL,則不計入。expression可以是:一個列名 (
COUNT(column_name)):統(tǒng)計該列中非 NULL 值的數(shù)量。這是最常見的使用方式。一個常量 (
COUNT(1),COUNT('abc')):因為常量永遠是非 NULL 的,所以COUNT(1)或COUNT('任何常量')的行為幾乎總是等同于COUNT(*),統(tǒng)計總行數(shù)。現(xiàn)代 MySQL 優(yōu)化器通常會將COUNT(1)轉換為COUNT(*)來執(zhí)行。一個表達式 (
COUNT(UPPER(name)),COUNT(price * quantity)):先計算表達式,然后判斷結果是否為 NULL。
性能: 如果
expression是一個列名,MySQL 需要檢查該列的值是否為 NULL。如果該列沒有索引,對于大表來說,這可能比COUNT(*)稍慢一些(因為COUNT(*)可以利用存儲引擎的內部優(yōu)化)。如果expression是常量,性能通常與COUNT(*)相當。示例:
-- 統(tǒng)計 `users` 表中設置了郵箱 (`email` 列非 NULL) 的用戶數(shù) SELECT COUNT(email) FROM users; -- 統(tǒng)計 `orders` 表中總金額 (`total_amount`) 大于 100 的訂單數(shù)量 (假設 total_amount 可為 NULL) SELECT COUNT(total_amount > 100) FROM orders; -- 注意:`total_amount > 100` 的結果是布爾值 (TRUE, FALSE, 或 NULL)。在 MySQL 中,TRUE=1, FALSE=0, NULL=NULL。所以 COUNT 只會計入結果為 TRUE (1) 的非 NULL 行。 -- 更常見的寫法是結合 WHERE: SELECT COUNT(*) FROM orders WHERE total_amount > 100; -- 統(tǒng)計 `products` 表中 `name` 字段非 NULL 的產品數(shù)量 (等同于 COUNT(name)) SELECT COUNT(*) FROM products WHERE name IS NOT NULL; -- 另一種寫法
COUNT(DISTINCT expression)功能: 統(tǒng)計表達式
expression計算結果中不同(唯一、去重后)的非 NULL 值的數(shù)量。計數(shù)方式: 首先計算所有行中
expression的值,然后去除結果集中的 NULL 值,最后對剩下的非 NULL 值進行去重,統(tǒng)計去重后的數(shù)量。性能: 這是性能開銷最大的一種形式,因為它涉及到對所有非 NULL 值進行排序或使用哈希表來去重。對于大表,尤其是在沒有合適索引的情況下,可能會比較慢。
示例:
-- 統(tǒng)計 `users` 表中來自不同城市 (`city`) 的數(shù)量 (忽略 city 為 NULL 的行) SELECT COUNT(DISTINCT city) FROM users; -- 統(tǒng)計 `orders` 表中每個客戶 (`customer_id`) 下了多少種不同商品 (`product_id`) 的訂單 SELECT customer_id, COUNT(DISTINCT product_id) AS unique_products_ordered FROM orders GROUP BY customer_id;
重要特性與行為
COUNT()與 NULL:COUNT(*):不關心 NULL,統(tǒng)計所有行。COUNT(expression):只統(tǒng)計expression計算結果為非 NULL 的行。COUNT(DISTINCT expression):只統(tǒng)計expression計算結果為非 NULL 的值,并且對這些非 NULL 值進行去重計數(shù)。
聚合函數(shù):
COUNT()是一個聚合函數(shù)。它通常作用于一組行(可能是整個表,或者GROUP BY定義的每個組),并返回一個單一的匯總值。與
WHERE結合:WHERE子句在聚合發(fā)生之前過濾行。COUNT()只會計入通過WHERE條件過濾后的行。SELECT COUNT(*) FROM orders WHERE order_date >= '2024-01-01'; -- 統(tǒng)計2024年及之后的訂單數(shù)
與
GROUP BY結合:GROUP BY將數(shù)據(jù)分成多個組,COUNT()會為每個組單獨計算行數(shù)或非 NULL 值的數(shù)量。SELECT status, COUNT(*) AS order_count FROM orders GROUP BY status; -- 統(tǒng)計每種訂單狀態(tài)的數(shù)量
與
HAVING結合:HAVING子句在聚合發(fā)生之后過濾分組結果。它基于聚合結果(如COUNT(*))來篩選哪些分組應該出現(xiàn)在最終結果中。SELECT country, COUNT(*) AS user_count FROM users GROUP BY country HAVING user_count > 100; -- 只顯示用戶數(shù)超過100的國家
COUNT()返回類型:COUNT()函數(shù)返回一個BIGINT類型的值(64位整數(shù))。即使結果很小,返回類型也是BIGINT。沒有匹配行: 如果查詢沒有匹配任何行(例如,
WHERE條件太嚴格),COUNT()將返回 0。COUNT(DISTINCT ...)在沒有非 NULL 值時也返回 0。性能考慮(MyISAM vs InnoDB):
MyISAM: 對于
COUNT(*)且沒有WHERE條件的查詢(如SELECT COUNT(*) FROM myisam_table;),MyISAM 引擎會極其快速地返回結果,因為它直接在表的元數(shù)據(jù)中存儲了精確的總行數(shù)。InnoDB: InnoDB 引擎不存儲精確的總行數(shù)在元數(shù)據(jù)中。它需要掃描表(或最小的可用索引)來計算
COUNT(*)(即使沒有WHERE子句)。這是因為 MVCC(多版本并發(fā)控制)機制使得同時存在的事務可能看到表中不同版本的行數(shù)。因此,對于非常大的 InnoDB 表,SELECT COUNT(*) FROM huge_innodb_table;可能會比較慢。估算行數(shù)可以考慮查詢information_schema.TABLES表的TABLE_ROWS列(注意這是估算值,不精確?。?,或者使用計數(shù)器表、緩存等技術。
如何選擇使用哪種形式?
需要總行數(shù)? ?? 優(yōu)先使用
COUNT(*)。它是語義最清晰(計算行數(shù)),且在 MySQL 中通常性能最佳。需要統(tǒng)計特定列的非 NULL 值數(shù)量? ?? 使用
COUNT(column_name)。需要統(tǒng)計滿足特定條件的行數(shù)? ?? 結合
WHERE子句使用COUNT(*)(推薦) 或COUNT(1)。SELECT COUNT(*) FROM table WHERE condition;
需要統(tǒng)計某一列中不同值的數(shù)量(去重計數(shù))? ?? 使用
COUNT(DISTINCT column_name)。需要統(tǒng)計滿足某個表達式條件的行數(shù)? ?? 使用
COUNT(expression),或者更常見的,使用COUNT(*)+WHERE子句。SELECT COUNT(IF(score > 90, 1, NULL)) FROM students;-- 統(tǒng)計分數(shù)大于90的學生數(shù)等價于
SELECT COUNT(*) FROM students WHERE score > 90;(通常更推薦后者)
總結
COUNT() 函數(shù)是 MySQL 中用于計數(shù)的核心聚合函數(shù)。理解 COUNT(*)、COUNT(expression) 和 COUNT(DISTINCT expression) 之間的區(qū)別至關重要:
COUNT(*):統(tǒng)計所有行(推薦用于計數(shù)總行數(shù)或分組行數(shù))。COUNT(expression):統(tǒng)計expression結果非 NULL 的行數(shù)(用于統(tǒng)計特定列的非 NULL 值)。COUNT(DISTINCT expression):統(tǒng)計expression結果中不同(唯一)的非 NULL 值的數(shù)量(用于去重計數(shù))。
根據(jù)你的具體需求(是統(tǒng)計行數(shù)、特定列的非 NULL 值數(shù)、還是唯一值數(shù))選擇正確的形式,并結合 WHERE、GROUP BY、HAVING 子句來精確控制計數(shù)范圍
到此這篇關于MySQL count()聚合函數(shù)詳解的文章就介紹到這了,更多相關mysql count() 聚合函數(shù)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
MySQL數(shù)據(jù)庫中varchar類型的數(shù)字比較大小的方法
varchar類型的數(shù)據(jù)是不能直接比較大小的,那么MySQL數(shù)據(jù)庫中varchar類型如何進行數(shù)字比較大小的,本文就詳細的介紹一下2021-11-11
mysql 直接拷貝data 目錄下文件還原數(shù)據(jù)的實現(xiàn)
這篇文章主要介紹了mysql 直接拷貝data 目錄下文件還原數(shù)據(jù)的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
解決MySQL啟動報錯:ERROR 2003 (HY000): Can''t connect to MySQL serv
這篇文章主要介紹了解決MySQL啟動報錯:ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061),本文解釋了如何解決該問題,以下就是詳細內容,需要的朋友可以參考下2021-07-07
mysql如何修改表結構(alter table),多列/多字段
這篇文章主要介紹了mysql如何修改表結構(alter table),多列/多字段問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12
mysql根據(jù)逗號將一行數(shù)據(jù)拆分成多行數(shù)據(jù)
本文主要介紹了mysql根據(jù)逗號將一行數(shù)據(jù)拆分成多行數(shù)據(jù),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12

