news 2026/11/4 11:32:41

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【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值的行数,适用于统计特定列中的有效数据。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 23:30:07

英雄联盟开源工具LeaguePrank:安全合规的游戏界面个性化定制方案

英雄联盟开源工具LeaguePrank:安全合规的游戏界面个性化定制方案 【免费下载链接】LeaguePrank 项目地址: https://gitcode.com/gh_mirrors/le/LeaguePrank 你是否曾因游戏界面千篇一律而感到乏味?是否想展示个性化段位却担心账号安全&#xff1…

作者头像 李华
网站建设 2026/10/4 23:30:40

黑丝空姐-造相Z-Turbo与LSTM:时序创意生成的探索

黑丝空姐-造相Z-Turbo与LSTM:时序创意生成的探索 1. 引言 你有没有想过,让AI帮你画一个连续的故事?比如,一位空姐从登机、服务乘客到航班落地的完整过程,每一帧画面都连贯自然,像一部微电影的分镜。这正是…

作者头像 李华
网站建设 2026/10/4 23:40:53

Revit二次开发实战:项目基点的动态控制与坐标转换

1. 项目基点:BIM协同的“定海神针”与开发者的“必争之地” 如果你在Revit里做过几个项目,尤其是那种需要多专业、多团队协同的大项目,那你肯定对“项目基点”这四个字又爱又恨。爱它,是因为它就像建筑世界里的“经纬度原点”&…

作者头像 李华
网站建设 2026/10/4 23:40:54

Android12弹窗高斯模糊实战:Style与API两种方案对比(附完整代码)

Android 12 弹窗高斯模糊实战:Style与API两种方案深度抉择 最近在重构一个老项目的UI组件库,其中一个高频需求就是让各种弹窗、对话框的背景变得“高级”起来。用户反馈说,生硬的纯色遮罩或者简单的半透明效果已经有些审美疲劳,希…

作者头像 李华
网站建设 2026/10/4 23:32:42

LabVIEW实战解析:巧用数组与循环结构实现数字特征识别

1. 从“水仙花数”说起:为什么图形化编程也能玩转数学逻辑? 大家好,我是老张,在自动化测试和测控领域用LabVIEW摸爬滚打了十几年。今天想和大家聊一个特别有意思的话题:怎么用LabVIEW里看似简单的数组和for循环&#x…

作者头像 李华
网站建设 2026/10/4 23:32:59

实战指南 | ABAQUS多尺度网格划分优化策略与手动控制技巧

1. 为什么你需要手动控制多尺度网格划分? 如果你用过ABAQUS的自动网格划分,肯定遇到过这种情况:明明只想把螺栓孔周围或者应力集中区画得密一点,结果软件“自作主张”地把整个模型都画成了密密麻麻的小网格,计算时间直…

作者头像 李华