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

2024-06-23 11:04
文章标签 sql 区别 count database 列名

本文主要是介绍【SQL】count(1)、count(*) 与 count(列名) 的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在 SQL 中,COUNT 函数用于计算查询结果集中的行数。COUNT(1)COUNT(*)COUNT(列名) 都可以用来统计行数,但它们在实现细节和使用场景上有一些区别。以下是详细的解释:

1. COUNT(1)

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

2. COUNT(*)

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

3. COUNT(列名)

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

示例代码

下面是一个使用 JDBC 示例代码,展示如何使用 COUNT(1)COUNT(*)COUNT(列名)

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;public class CountExample {private static final String JDBC_URL = "jdbc:mysql://localhost:3306/yourdatabase";private static final String JDBC_USER = "yourusername";private static final String JDBC_PASSWORD = "yourpassword";public static void main(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 数据库中进行测试。请确保表中有足够多的数据,以便更明显地观察执行时间的差异。

创建测试表并插入数据
CREATE TABLE employees (id INT AUTO_INCREMENT PRIMARY KEY,department_id INT,name VARCHAR(255),created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);-- 插入大量数据
INSERT INTO employees (department_id, name) 
SELECT FLOOR(RAND() * 10), CONCAT('Employee', FLOOR(RAND() * 1000))
FROM (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) t1
CROSS JOIN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) t2
CROSS JOIN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) t3
CROSS JOIN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) t4
CROSS JOIN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) t5;
执行计数查询并记录执行时间
-- 计时 COUNT(1)
SET @start_time = NOW(6);
SELECT COUNT(1) FROM employees;
SELECT TIMEDIFF(NOW(6), @start_time) AS execution_time;-- 计时 COUNT(*)
SET @start_time = NOW(6);
SELECT COUNT(*) FROM employees;
SELECT TIMEDIFF(NOW(6), @start_time) AS execution_time;-- 计时 COUNT(department_id)
SET @start_time = NOW(6);
SELECT COUNT(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】count(1)、count(*) 与 count(列名) 的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1086971

相关文章

MySQL 中的 JSON 查询案例详解

《MySQL中的JSON查询案例详解》:本文主要介绍MySQL的JSON查询的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 的 jsON 路径格式基本结构路径组件详解特殊语法元素实际示例简单路径复杂路径简写操作符注意MySQL 的 J

Windows 上如果忘记了 MySQL 密码 重置密码的两种方法

《Windows上如果忘记了MySQL密码重置密码的两种方法》:本文主要介绍Windows上如果忘记了MySQL密码重置密码的两种方法,本文通过两种方法结合实例代码给大家介绍的非常详细,感... 目录方法 1:以跳过权限验证模式启动 mysql 并重置密码方法 2:使用 my.ini 文件的临时配置在 Wi

MySQL重复数据处理的七种高效方法

《MySQL重复数据处理的七种高效方法》你是不是也曾遇到过这样的烦恼:明明系统测试时一切正常,上线后却频频出现重复数据,大批量导数据时,总有那么几条不听话的记录导致整个事务莫名回滚,今天,我就跟大家分... 目录1. 重复数据插入问题分析1.1 问题本质1.2 常见场景图2. 基础解决方案:使用异常捕获3.

SQL中redo log 刷⼊磁盘的常见方法

《SQL中redolog刷⼊磁盘的常见方法》本文主要介绍了SQL中redolog刷⼊磁盘的常见方法,将redolog刷入磁盘的方法确保了数据的持久性和一致性,下面就来具体介绍一下,感兴趣的可以了解... 目录Redo Log 刷入磁盘的方法Redo Log 刷入磁盘的过程代码示例(伪代码)在数据库系统中,r

mysql中的group by高级用法

《mysql中的groupby高级用法》MySQL中的GROUPBY是数据聚合分析的核心功能,主要用于将结果集按指定列分组,并结合聚合函数进行统计计算,下面给大家介绍mysql中的groupby用法... 目录一、基本语法与核心功能二、基础用法示例1. 单列分组统计2. 多列组合分组3. 与WHERE结合使

Mysql用户授权(GRANT)语法及示例解读

《Mysql用户授权(GRANT)语法及示例解读》:本文主要介绍Mysql用户授权(GRANT)语法及示例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql用户授权(GRANT)语法授予用户权限语法GRANT语句中的<权限类型>的使用WITH GRANT

Mysql如何解决死锁问题

《Mysql如何解决死锁问题》:本文主要介绍Mysql如何解决死锁问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录【一】mysql中锁分类和加锁情况【1】按锁的粒度分类全局锁表级锁行级锁【2】按锁的模式分类【二】加锁方式的影响因素【三】Mysql的死锁情况【1

SQL BETWEEN 的常见用法小结

《SQLBETWEEN的常见用法小结》BETWEEN操作符是SQL中非常有用的工具,它允许你快速选取某个范围内的值,本文给大家介绍SQLBETWEEN的常见用法,感兴趣的朋友一起看看吧... 在SQL中,BETWEEN是一个操作符,用于选取介于两个值之间的数据。它包含这两个边界值。BETWEEN操作符常用

MySQL索引的优化之LIKE模糊查询功能实现

《MySQL索引的优化之LIKE模糊查询功能实现》:本文主要介绍MySQL索引的优化之LIKE模糊查询功能实现,本文通过示例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前缀匹配优化二、后缀匹配优化三、中间匹配优化四、覆盖索引优化五、减少查询范围六、避免通配符开头七、使用外部搜索引擎八、分

MySql match against工具详细用法

《MySqlmatchagainst工具详细用法》在MySQL中,MATCH……AGAINST是全文索引(Full-Textindex)的查询语法,它允许你对文本进行高效的全文搜素,支持自然语言搜... 目录一、全文索引的基本概念二、创建全文索引三、自然语言搜索四、布尔搜索五、相关性排序六、全文索引的限制七