在 MySQL 里,COUNT() 函数是常用的聚合函数,用于统计记录数量。COUNT() 有几种不同的使用方式,下面详细介绍并对比它们的特点、使用场景和性能差异。
COUNT(*) 用于统计查询结果集中的记录行数,无论这些行中的列是否包含 NULL 值。它会对表中的每一行进行计数。
SELECT COUNT(*) FROM employees;
此查询会返回 employees 表中的记录总数。
- 特点:不考虑列的值是否为
NULL,只要有行存在就会计数。
- 适用场景:当你只需要知道表中有多少行记录,而不关心具体列的值时,使用
COUNT(*) 最为合适。
- 在大多数数据库引擎中,
COUNT(*) 经过了优化,通常可以直接从存储引擎的元数据中获取行数,性能较高。不过,在某些情况下,例如表数据量巨大且存在复杂的过滤条件时,它可能需要扫描全量数据,性能会有所下降。
COUNT(1) 和 COUNT(*) 在功能上基本相同,也是用于统计查询结果集中的记录行数。这里的 1 可以是任意常量,它只是用来表示每行都会被计数。
SELECT COUNT(1) FROM employees;
这个查询同样会返回 employees 表中的记录总数。
- 特点:和
COUNT(*) 功能一致,只是写法上有所不同。
- 适用场景:与
COUNT(*) 一样,适用于只需要统计记录行数的场景。
- 在性能方面,
COUNT(1) 和 COUNT(*) 几乎没有差别。在大多数数据库引擎中,它们的执行计划是相同的,数据库会将 COUNT(1) 优化成和 COUNT(*) 一样的操作。
COUNT(column_name) 用于统计指定列中非 NULL 值的数量。只有当指定列的值不为 NULL 时,该行才会被计数。
SELECT COUNT(salary) FROM employees;
此查询会返回 employees 表中 salary 列不为 NULL 的记录数量。
- 特点:只统计指定列中非
NULL 值的行数。
- 适用场景:当你需要统计某列中有实际值的记录数量时,使用
COUNT(column_name)。比如,统计有多少员工有工资记录(即 salary 列不为 NULL)。
COUNT(column_name) 通常需要扫描指定列的值,以判断是否为 NULL。如果该列上有索引,数据库可能会利用索引来提高查询性能;如果没有索引,则可能需要全表扫描,性能相对较低。
COUNT(DISTINCT column_name) 用于统计指定列中不同非 NULL 值的数量。它会先去除指定列中的重复值和 NULL 值,然后对剩余的不同值进行计数。
SELECT COUNT(DISTINCT department_id) FROM employees;
这个查询会返回 employees 表中不同 department_id 的数量。
- 特点:去除重复值和
NULL 值后进行计数。
- 适用场景:当你需要了解某列中有多少个不同的值时,使用
COUNT(DISTINCT column_name)。例如,统计公司有多少个不同的部门。
COUNT(DISTINCT column_name) 的性能通常较差,因为它需要对指定列进行排序和去重操作。如果数据量较大,这些操作会消耗较多的资源和时间。在这种情况下,如果对性能有较高要求,可以考虑使用临时表或其他优化方法。
| 函数形式 | 功能 | 性能 | 适用场景 |
COUNT(*) |
统计记录行数,不考虑列值是否为 NULL |
通常较高,可能直接从元数据获取行数 |
统计全量记录数 |
COUNT(1) |
功能与 COUNT(*) 相同 |
与 COUNT(*) 基本无差异 |
统计全量记录数 |
COUNT(column_name) |
统计指定列中非 NULL 值的数量 |
取决于列上是否有索引,可能需全表扫描 |
统计某列有实际值的记录数 |
COUNT(DISTINCT column_name) |
统计指定列中不同非 NULL 值的数量 |
较差 |