SQL中count(1)、count(*)?與?count(列名)的區(qū)別詳細(xì)解釋
前言
在 SQL 中,COUNT 函數(shù)用于計(jì)算查詢結(jié)果集中的行數(shù)。COUNT(1)、COUNT(*) 和 COUNT(列名) 都可以用來統(tǒng)計(jì)行數(shù),但它們在實(shí)現(xiàn)細(xì)節(jié)和使用場景上有一些區(qū)別。以下是詳細(xì)的解釋:
1. COUNT(1)
- 定義:
COUNT(1)計(jì)算查詢結(jié)果集中的行數(shù)。 - 實(shí)現(xiàn): 在執(zhí)行過程中,
COUNT(1)會將1作為一個非空的常量值,并對每一行進(jìn)行計(jì)數(shù)。 - 效率: 現(xiàn)代的 SQL 優(yōu)化器通常會將
COUNT(1)和COUNT(*)優(yōu)化為相同的執(zhí)行計(jì)劃,因此性能基本相同。 - 用途: 適用于計(jì)算總行數(shù),與
COUNT(*)無區(qū)別。
SELECT COUNT(1) FROM employees;
2. COUNT(*)
- 定義:
COUNT(*)計(jì)算查詢結(jié)果集中的總行數(shù),包括所有列,不會忽略任何行,即使某些列包含NULL。 - 實(shí)現(xiàn): SQL 優(yōu)化器會對
COUNT(*)進(jìn)行優(yōu)化,將其轉(zhuǎn)換為統(tǒng)計(jì)行數(shù)的操作。 - 效率: 通常是最常用和推薦的方式,因?yàn)槠湔Z義明確且優(yōu)化器能夠很好地處理。
- 用途: 適用于計(jì)算總行數(shù),性能通常優(yōu)于
COUNT(列名)。
SELECT COUNT(*) FROM employees;
3. COUNT(列名)
- 定義:
COUNT(列名)計(jì)算查詢結(jié)果集中某一列非NULL值的行數(shù)。 - 實(shí)現(xiàn): 只有當(dāng)指定列的值不為
NULL時(shí),該行才會被計(jì)入結(jié)果。 - 效率: 由于需要檢查每行中的特定列是否為
NULL,性能可能略低于COUNT(*)和COUNT(1)。 - 用途: 適用于計(jì)算某一特定列中非
NULL值的數(shù)量。
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(列名) 進(jìn)行統(tǒng)計(jì)查詢。請根據(jù)需要調(diào)整數(shù)據(jù)庫連接字符串、用戶名、密碼和 SQL 語句。
執(zhí)行速度
對 COUNT(1)、COUNT(*) 和 COUNT(列名) 的執(zhí)行速度進(jìn)行排序,通常在現(xiàn)代的 SQL 數(shù)據(jù)庫管理系統(tǒng)中,COUNT(1) 和 COUNT(*) 的性能基本相同,而 COUNT(列名) 的性能可能略低一些。排序如下:
- COUNT(1)
- COUNT(*)
- COUNT(列名)
詳細(xì)解釋
1. COUNT(1)
- 執(zhí)行速度:
COUNT(1)只是將每一行的計(jì)數(shù)加一,現(xiàn)代 SQL 優(yōu)化器通常會將COUNT(1)和COUNT(*)優(yōu)化為相同的執(zhí)行計(jì)劃,因此執(zhí)行速度非??臁?/li> - 優(yōu)化器行為: 優(yōu)化器能夠識別
COUNT(1)的語義并進(jìn)行優(yōu)化處理,使其與COUNT(*)的性能基本一致。
2. COUNT(*)
- 執(zhí)行速度:
COUNT(*)計(jì)算表中所有行的數(shù)量,包括所有列,不忽略任何行?,F(xiàn)代 SQL 優(yōu)化器對此有非常好的優(yōu)化,因此執(zhí)行速度也非???,通常與COUNT(1)無異。 - 優(yōu)化器行為: 優(yōu)化器會將
COUNT(*)優(yōu)化為高效的行計(jì)數(shù)操作。
3. COUNT(列名)
- 執(zhí)行速度:
COUNT(列名)只計(jì)算指定列非NULL值的行數(shù)。在執(zhí)行過程中,數(shù)據(jù)庫需要檢查每一行中特定列是否為NULL,這會增加一些額外的處理時(shí)間。 - 優(yōu)化器行為: 盡管現(xiàn)代優(yōu)化器對
COUNT(列名)也有優(yōu)化,但由于需要額外的NULL檢查,性能可能略低于COUNT(1)和COUNT(*)。
示例驗(yàn)證
為了驗(yàn)證上述結(jié)論,可以使用以下 SQL 腳本在 MySQL 或其他 SQL 數(shù)據(jù)庫中進(jìn)行測試。請確保表中有足夠多的數(shù)據(jù),以便更明顯地觀察執(zhí)行時(shí)間的差異。
創(chuàng)建測試表并插入數(shù)據(jù)
CREATE TABLE employees (
id INT AUTO_INCREMENT PRIMARY KEY,
department_id INT,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入大量數(shù)據(jù)
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;
執(zhí)行計(jì)數(shù)查詢并記錄執(zhí)行時(shí)間
-- 計(jì)時(shí) COUNT(1) SET @start_time = NOW(6); SELECT COUNT(1) FROM employees; SELECT TIMEDIFF(NOW(6), @start_time) AS execution_time; -- 計(jì)時(shí) COUNT(*) SET @start_time = NOW(6); SELECT COUNT(*) FROM employees; SELECT TIMEDIFF(NOW(6), @start_time) AS execution_time; -- 計(jì)時(shí) COUNT(department_id) SET @start_time = NOW(6); SELECT COUNT(department_id) FROM employees; SELECT TIMEDIFF(NOW(6), @start_time) AS execution_time;
這些查詢將顯示每個 COUNT 語句的執(zhí)行時(shí)間。通常,COUNT(1) 和 COUNT(*) 的執(zhí)行時(shí)間幾乎相同,而 COUNT(列名) 的執(zhí)行時(shí)間可能稍長一些。
總結(jié)
COUNT(1): 計(jì)算查詢結(jié)果集中的行數(shù),性能與COUNT(*)基本相同。COUNT(*): 計(jì)算查詢結(jié)果集中的總行數(shù),包括所有列,不忽略任何行,通常是最常用和推薦的方式。COUNT(列名): 計(jì)算查詢結(jié)果集中某一列非NULL值的行數(shù),適用于統(tǒng)計(jì)特定列中的有效數(shù)據(jù)。
到此這篇關(guān)于SQL中count(1)、count(*) 與 count(列名)區(qū)別的文章就介紹到這了,更多相關(guān)SQL中count(1)、count(*) 與 count(列名)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- mysql count(*)分組之后IFNULL無效問題
- Sql根據(jù)不同條件統(tǒng)計(jì)總數(shù)的方法(count和sum)
- MySQL數(shù)據(jù)庫統(tǒng)計(jì)函數(shù)COUNT的使用及說明
- mysql?count()函數(shù)不計(jì)算null和空值問題
- mysql數(shù)據(jù)庫之count()函數(shù)和sum()函數(shù)用法及區(qū)別說明
- mysql一條sql查出多個條件不同的sum或count問題
- MySQL中的count(*)?和?count(1)?區(qū)別性能對比分析
- SQL 中 COUNT 的用法示例詳解
相關(guān)文章
MySQL使用select語句查詢指定表中指定列(字段)的數(shù)據(jù)
本文介紹MySQL數(shù)據(jù)庫中執(zhí)行select查詢語句,查詢指定列的數(shù)據(jù),即指定字段的數(shù)據(jù),需要的朋友可以參考下2016-11-11
sql如何使用group by分組,同時(shí)查詢其它字段
文章介紹了使用SQL的GROUP BY進(jìn)行分組查詢時(shí)的一些規(guī)則和技巧,主要強(qiáng)調(diào)了在SELECT后面的字段要么是聚合函數(shù)的一部分,要么必須包含在GROUP BY子句中,此外,文章還討論了如何在GROUP BY時(shí)查詢其他字段,通過使用MAX或MIN函數(shù)來實(shí)現(xiàn)2024-12-12

