0


【SQL】count(1)、count(*) 与 count(列名) 的区别

在 SQL 中,

COUNT

函数用于计算查询结果集中的行数。

COUNT(1)

COUNT(*)

COUNT(列名)

都可以用来统计行数,但它们在实现细节和使用场景上有一些区别。以下是详细的解释:

1. COUNT(1)

  • 定义: COUNT(1) 计算查询结果集中的行数。
  • 实现: 在执行过程中,COUNT(1) 会将 1 作为一个非空的常量值,并对每一行进行计数。
  • 效率: 现代的 SQL 优化器通常会将 COUNT(1)COUNT(*) 优化为相同的执行计划,因此性能基本相同。
  • 用途: 适用于计算总行数,与 COUNT(*) 无区别。
SELECTCOUNT(1)FROM employees;

2. COUNT(*)

  • 定义: COUNT(*) 计算查询结果集中的总行数,包括所有列,不会忽略任何行,即使某些列包含 NULL
  • 实现: SQL 优化器会对 COUNT(*) 进行优化,将其转换为统计行数的操作。
  • 效率: 通常是最常用和推荐的方式,因为其语义明确且优化器能够很好地处理。
  • 用途: 适用于计算总行数,性能通常优于 COUNT(列名)
SELECTCOUNT(*)FROM employees;

3. COUNT(列名)

  • 定义: COUNT(列名) 计算查询结果集中某一列非 NULL 值的行数。
  • 实现: 只有当指定列的值不为 NULL 时,该行才会被计入结果。
  • 效率: 由于需要检查每行中的特定列是否为 NULL,性能可能略低于 COUNT(*)COUNT(1)
  • 用途: 适用于计算某一特定列中非 NULL 值的数量。
SELECTCOUNT(department_id)FROM employees;

示例代码

下面是一个使用 JDBC 示例代码,展示如何使用

COUNT(1)

COUNT(*)

COUNT(列名)

importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.Statement;importjava.sql.ResultSet;importjava.sql.SQLException;publicclassCountExample{privatestaticfinalStringJDBC_URL="jdbc:mysql://localhost:3306/yourdatabase";privatestaticfinalStringJDBC_USER="yourusername";privatestaticfinalStringJDBC_PASSWORD="yourpassword";publicstaticvoidmain(String[] args){try(Connection conn =DriverManager.getConnection(JDBC_URL,JDBC_USER,JDBC_PASSWORD);Statement stmt = conn.createStatement()){// 使用 COUNT(1)String count1SQL ="SELECT COUNT(1) AS total FROM employees";ResultSet rs1 = stmt.executeQuery(count1SQL);if(rs1.next()){int total1 = rs1.getInt("total");System.out.println("Total rows (COUNT(1)): "+ total1);}// 使用 COUNT(*)String countAllSQL ="SELECT COUNT(*) AS total FROM employees";ResultSet rsAll = stmt.executeQuery(countAllSQL);if(rsAll.next()){int totalAll = rsAll.getInt("total");System.out.println("Total rows (COUNT(*)): "+ totalAll);}// 使用 COUNT(column)String countColumnSQL ="SELECT COUNT(department_id) AS total FROM employees";ResultSet rsColumn = stmt.executeQuery(countColumnSQL);if(rsColumn.next()){int totalColumn = rsColumn.getInt("total");System.out.println("Total rows (COUNT(department_id)): "+ totalColumn);}}catch(SQLException e){
            e.printStackTrace();}}}

在上述代码中,演示了如何使用

COUNT(1)

COUNT(*)

COUNT(列名)

进行统计查询。请根据需要调整数据库连接字符串、用户名、密码和 SQL 语句。

执行速度

COUNT(1)

COUNT(*)

COUNT(列名)

的执行速度进行排序,通常在现代的 SQL 数据库管理系统中,

COUNT(1)

COUNT(*)

的性能基本相同,而

COUNT(列名)

的性能可能略低一些。排序如下:

  1. COUNT(1)
  2. COUNT(*)
  3. COUNT(列名)

详细解释

1. COUNT(1)
  • 执行速度: COUNT(1) 只是将每一行的计数加一,现代 SQL 优化器通常会将 COUNT(1)COUNT(*) 优化为相同的执行计划,因此执行速度非常快。
  • 优化器行为: 优化器能够识别 COUNT(1) 的语义并进行优化处理,使其与 COUNT(*) 的性能基本一致。
2. COUNT(*)
  • 执行速度: COUNT(*) 计算表中所有行的数量,包括所有列,不忽略任何行。现代 SQL 优化器对此有非常好的优化,因此执行速度也非常快,通常与 COUNT(1) 无异。
  • 优化器行为: 优化器会将 COUNT(*) 优化为高效的行计数操作。
3. COUNT(列名)
  • 执行速度: COUNT(列名) 只计算指定列非 NULL 值的行数。在执行过程中,数据库需要检查每一行中特定列是否为 NULL,这会增加一些额外的处理时间。
  • 优化器行为: 尽管现代优化器对 COUNT(列名) 也有优化,但由于需要额外的 NULL 检查,性能可能略低于 COUNT(1)COUNT(*)

示例验证

为了验证上述结论,可以使用以下 SQL 脚本在 MySQL 或其他 SQL 数据库中进行测试。请确保表中有足够多的数据,以便更明显地观察执行时间的差异。

创建测试表并插入数据
CREATETABLE employees (
    id INTAUTO_INCREMENTPRIMARYKEY,
    department_id INT,
    name VARCHAR(255),
    created_at TIMESTAMPDEFAULTCURRENT_TIMESTAMP);-- 插入大量数据INSERTINTO employees (department_id, name)SELECT FLOOR(RAND()*10), CONCAT('Employee', FLOOR(RAND()*1000))FROM(SELECT1UNIONALLSELECT2UNIONALLSELECT3UNIONALLSELECT4) t1
CROSSJOIN(SELECT1UNIONALLSELECT2UNIONALLSELECT3UNIONALLSELECT4) t2
CROSSJOIN(SELECT1UNIONALLSELECT2UNIONALLSELECT3UNIONALLSELECT4) t3
CROSSJOIN(SELECT1UNIONALLSELECT2UNIONALLSELECT3UNIONALLSELECT4) t4
CROSSJOIN(SELECT1UNIONALLSELECT2UNIONALLSELECT3UNIONALLSELECT4) t5;
执行计数查询并记录执行时间
-- 计时 COUNT(1)SET@start_time=NOW(6);SELECTCOUNT(1)FROM employees;SELECT TIMEDIFF(NOW(6),@start_time)AS execution_time;-- 计时 COUNT(*)SET@start_time=NOW(6);SELECTCOUNT(*)FROM employees;SELECT TIMEDIFF(NOW(6),@start_time)AS execution_time;-- 计时 COUNT(department_id)SET@start_time=NOW(6);SELECTCOUNT(department_id)FROM employees;SELECT TIMEDIFF(NOW(6),@start_time)AS execution_time;

这些查询将显示每个

COUNT

语句的执行时间。通常,

COUNT(1)

COUNT(*)

的执行时间几乎相同,而

COUNT(列名)

的执行时间可能稍长一些。

总结

  • COUNT(1): 计算查询结果集中的行数,性能与 COUNT(*) 基本相同。
  • COUNT(*): 计算查询结果集中的总行数,包括所有列,不忽略任何行,通常是最常用和推荐的方式。
  • COUNT(列名): 计算查询结果集中某一列非 NULL 值的行数,适用于统计特定列中的有效数据。
标签: sql 数据库

本文转载自: https://blog.csdn.net/hui_zai_/article/details/139756983
版权归原作者 灰_灰丶灰 所有, 如有侵权,请联系我们删除。

“【SQL】count(1)、count(*) 与 count(列名) 的区别”的评论:

还没有评论