SQL中count(1)、count(*)?與?count(列名)的區(qū)別詳細解釋
前言
在 SQL 中,COUNT
函數(shù)用于計算查詢結(jié)果集中的行數(shù)。COUNT(1)
、COUNT(*)
和 COUNT(列名)
都可以用來統(tǒng)計行數(shù),但它們在實現(xiàn)細節(jié)和使用場景上有一些區(qū)別。以下是詳細的解釋:
1. COUNT(1)
- 定義:
COUNT(1)
計算查詢結(jié)果集中的行數(shù)。 - 實現(xiàn): 在執(zhí)行過程中,
COUNT(1)
會將1
作為一個非空的常量值,并對每一行進行計數(shù)。 - 效率: 現(xiàn)代的 SQL 優(yōu)化器通常會將
COUNT(1)
和COUNT(*)
優(yōu)化為相同的執(zhí)行計劃,因此性能基本相同。 - 用途: 適用于計算總行數(shù),與
COUNT(*)
無區(qū)別。
SELECT COUNT(1) FROM employees;
2. COUNT(*)
- 定義:
COUNT(*)
計算查詢結(jié)果集中的總行數(shù),包括所有列,不會忽略任何行,即使某些列包含NULL
。 - 實現(xiàn): SQL 優(yōu)化器會對
COUNT(*)
進行優(yōu)化,將其轉(zhuǎn)換為統(tǒng)計行數(shù)的操作。 - 效率: 通常是最常用和推薦的方式,因為其語義明確且優(yōu)化器能夠很好地處理。
- 用途: 適用于計算總行數(shù),性能通常優(yōu)于
COUNT(列名)
。
SELECT COUNT(*) FROM employees;
3. COUNT(列名)
- 定義:
COUNT(列名)
計算查詢結(jié)果集中某一列非NULL
值的行數(shù)。 - 實現(xiàn): 只有當(dāng)指定列的值不為
NULL
時,該行才會被計入結(jié)果。 - 效率: 由于需要檢查每行中的特定列是否為
NULL
,性能可能略低于COUNT(*)
和COUNT(1)
。 - 用途: 適用于計算某一特定列中非
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(列名)
進行統(tǒng)計查詢。請根據(jù)需要調(diào)整數(shù)據(jù)庫連接字符串、用戶名、密碼和 SQL 語句。
執(zhí)行速度
對 COUNT(1)
、COUNT(*)
和 COUNT(列名)
的執(zhí)行速度進行排序,通常在現(xiàn)代的 SQL 數(shù)據(jù)庫管理系統(tǒng)中,COUNT(1)
和 COUNT(*)
的性能基本相同,而 COUNT(列名)
的性能可能略低一些。排序如下:
- COUNT(1)
- COUNT(*)
- COUNT(列名)
詳細解釋
1. COUNT(1)
- 執(zhí)行速度:
COUNT(1)
只是將每一行的計數(shù)加一,現(xiàn)代 SQL 優(yōu)化器通常會將COUNT(1)
和COUNT(*)
優(yōu)化為相同的執(zhí)行計劃,因此執(zhí)行速度非???。 - 優(yōu)化器行為: 優(yōu)化器能夠識別
COUNT(1)
的語義并進行優(yōu)化處理,使其與COUNT(*)
的性能基本一致。
2. COUNT(*)
- 執(zhí)行速度:
COUNT(*)
計算表中所有行的數(shù)量,包括所有列,不忽略任何行。現(xiàn)代 SQL 優(yōu)化器對此有非常好的優(yōu)化,因此執(zhí)行速度也非常快,通常與COUNT(1)
無異。 - 優(yōu)化器行為: 優(yōu)化器會將
COUNT(*)
優(yōu)化為高效的行計數(shù)操作。
3. COUNT(列名)
- 執(zhí)行速度:
COUNT(列名)
只計算指定列非NULL
值的行數(shù)。在執(zhí)行過程中,數(shù)據(jù)庫需要檢查每一行中特定列是否為NULL
,這會增加一些額外的處理時間。 - 優(yōu)化器行為: 盡管現(xiàn)代優(yōu)化器對
COUNT(列名)
也有優(yōu)化,但由于需要額外的NULL
檢查,性能可能略低于COUNT(1)
和COUNT(*)
。
示例驗證
為了驗證上述結(jié)論,可以使用以下 SQL 腳本在 MySQL 或其他 SQL 數(shù)據(jù)庫中進行測試。請確保表中有足夠多的數(shù)據(jù),以便更明顯地觀察執(zhí)行時間的差異。
創(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í)行計數(shù)查詢并記錄執(zhí)行時間
-- 計時 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
語句的執(zhí)行時間。通常,COUNT(1)
和 COUNT(*)
的執(zhí)行時間幾乎相同,而 COUNT(列名)
的執(zhí)行時間可能稍長一些。
總結(jié)
COUNT(1)
: 計算查詢結(jié)果集中的行數(shù),性能與COUNT(*)
基本相同。COUNT(*)
: 計算查詢結(jié)果集中的總行數(shù),包括所有列,不忽略任何行,通常是最常用和推薦的方式。COUNT(列名)
: 計算查詢結(jié)果集中某一列非NULL
值的行數(shù),適用于統(tǒng)計特定列中的有效數(shù)據(jù)。
到此這篇關(guān)于SQL中count(1)、count(*) 與 count(列名)區(qū)別的文章就介紹到這了,更多相關(guān)SQL中count(1)、count(*) 與 count(列名)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL使用select語句查詢指定表中指定列(字段)的數(shù)據(jù)
本文介紹MySQL數(shù)據(jù)庫中執(zhí)行select查詢語句,查詢指定列的數(shù)據(jù),即指定字段的數(shù)據(jù),需要的朋友可以參考下2016-11-11