Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

COUNT(*) vs COUNT(column) ใน MySQL: นับแถว vs นับค่าไม่เป็น NULL

หลายคนเข้าใจผิดว่า COUNT(*) และ COUNT(column) ให้ผลลัพธ์เหมือนกัน แต่จริงๆ แล้ว **ต่างกัน** เมื่อคอลัมน์มีค่า NULL

ความแตกต่างสำคัญ

ฟังก์ชันนับอะไรรวม NULL
COUNT(*)จำนวนแถวทั้งหมด (Rows)✅ ใช่
COUNT(column)จำนวนค่าที่ **ไม่เป็น NULL**❌ ไม่
COUNT(DISTINCT column)จำนวนค่าที่ไม่ซ้ำและไม่เป็น NULL❌ ไม่

ตัวอย่างแสดงความแตกต่าง

1. สร้างตารางและเพิ่มข้อมูล (มี NULL)

mysql> CREATE TABLE CountingDemo (BookId INT);
Query OK, 0 rows affected (0.60 sec)

mysql> INSERT INTO CountingDemo VALUES (100), (NULL), (200), (300), (NULL);

2. ดูข้อมูล

mysql> SELECT * FROM CountingDemo;
+--------+
| BookId |
+--------+
| 100    |
| NULL   |
| 200    |
| 300    |
| NULL   |
+--------+
5 rows in set (0.00 sec)

3. COUNT(*) - นับทุกแถว

mysql> SELECT COUNT(*) AS AllRows FROM CountingDemo;
+---------+
| AllRows |
+---------+
| 5       |
+---------+
1 row in set (0.00 sec)

4. COUNT(BookId) - นับเฉพาะไม่ NULL

mysql> SELECT COUNT(BookId) AS NonNullValues FROM CountingDemo;
+---------------+
| NonNullValues |
+---------------+
| 3             |
+---------------+
1 row in set (0.00 sec)

เมื่อไหร่ควรใช้ COUNT(*)

  • ต้องการจำนวนแถวทั้งหมด (Row Count)
  • Primary Key / Not Null Column - ผลลัพธ์เหมือน COUNT(column)
  • เร็วกว่าในบาง Engine (MyISAM เก็บ Row Count ไว้)

เมื่อไหร่ควรใช้ COUNT(column)

  • ต้องการนับเฉพาะแถวที่มีข้อมูลในคอลัมน์นั้น
  • เช็ค Data Quality (มี NULL กี่แถว)
  • COUNT(*) - COUNT(column) = จำนวน NULL

ประสิทธิภาพ (Performance)

Storage EngineCOUNT(*)COUNT(column)
MyISAMO(1) - อ่านจาก MetadataO(N) - ต้อง Scan
InnoDBO(N) - Full ScanO(N) - Full Scan

InnoDB: ทั้งคู่ต้อง Scan เพราะ MVCC (แต่ละ Transaction เห็น Snapshot ต่างกัน)

Optimization Tips

  • ใช้ COUNT(1) แทน COUNT(*) - ผลลัพธ์เหมือนกัน บางคนเชื่อว่าเร็วกว่า (จริงๆ Optimizer จัดการเหมือนกัน)
  • หากต้องการ Count บ่อยๆ ควรเก็บ Counter แยก (Summary Table / Trigger)
  • EXPLAIN SELECT COUNT(*) FROM table ดู Execution Plan

COUNT กับ GROUP BY

SELECT category, COUNT(*) AS total_products, COUNT(discount) AS discounted_products
FROM products
GROUP BY category;