[คัดลอกและวางได้เลย] คู่มือการใช้ฟังก์ชัน COUNT ของ SQL อย่างละเอียด ตั้งแต่พื้นฐานจนถึงขั้นสูง
เมื่อพัฒนาเว็บไซต์หรือแอปพลิเคชัน เรามักจะเจอคำถามอย่าง “มีผู้ใช้งานทั้งหมดกี่คน?” หรือ “มีสินค้ากี่ประเภทในหมวดหมู่เฉพาะ?” ซึ่งในกรณีเช่นนี้ ฟังก์ชัน COUNT() ของ SQL จะมีประโยชน์อย่างมาก
COUNT() เป็นฟังก์ชันการรวม (aggregate function) ที่ใช้ในการนับจำนวนแถว (records) ในตาราง ฟังดูเรียบง่าย แต่ขึ้นอยู่กับวิธีใช้ เราสามารถดึงข้อมูลได้หลากหลายรูปแบบ ฟังก์ชันนี้มีความลึกและทรงพลังมาก ในบทความนี้เราจะอธิบายวิธีใช้งานตั้งแต่พื้นฐานไปจนถึงการประยุกต์ใช้จริง พร้อมโค้ดตัวอย่างที่สามารถคัดลอกและวางได้ทันที เหมาะสำหรับผู้เริ่มต้นที่ต้องการเป็นนักพัฒนาเว็บ
เป้าหมายของบทความนี้คือช่วยให้คุณได้สัมผัสความรู้สึกว่า “SQL มันทำงานได้จริงเมื่อเราเขียน!” ทิ้งทฤษฎีที่ซับซ้อนไว้ก่อน! เริ่มต้นจากการคัดลอกโค้ด รัน แล้วดูผลลัพธ์ เพื่อค้นหาความสนุกของ SQL ด้วยตัวคุณเอง
เริ่มต้นวอร์มอัป! สร้างข้อมูลตัวอย่าง
การจะทดลอง SQL ได้นั้น จำเป็นต้องมีตารางที่มีข้อมูล ในบทความนี้เราจะสร้างตาราง users ซึ่งเป็นรายการผู้ใช้ตัวอย่าง โค้ด SQL ด้านล่างนี้ใช้สำหรับสร้างตารางและใส่ข้อมูลทดสอบ
โค้ดทั้งหมดในบทความนี้จะอ้างอิงกับตาราง users นี้
-- ลบตารางหากมีอยู่แล้ว (เพื่อให้ทดลองซ้ำได้)
DROP TABLE IF EXISTS users;
-- สร้างตาราง users
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
prefecture TEXT NOT NULL,
email TEXT
);
-- เพิ่มข้อมูล
INSERT INTO users (id, name, prefecture, email) VALUES
(1, 'Taro Yamada', 'Tokyo', 'yamada@example.com'),
(2, 'Hanako Suzuki', 'Osaka', 'suzuki@example.com'),
(3, 'Jiro Sato', 'Tokyo', NULL),
(4, 'Sakura Ito', 'Fukuoka', 'ito@example.com'),
(5, 'Saburo Watanabe', 'Hokkaido', 'watanabe@example.com'),
(6, 'Shiro Takahashi', 'Tokyo', 'takahashi@example.com'),
(7, 'Misaki Tanaka', 'Osaka', NULL);
ตารางนี้ประกอบด้วยคอลัมน์ ID, ชื่อ, จังหวัด และอีเมล จุดสำคัญคืออีเมลของคุณ Sato (ID 3) และคุณ Tanaka (ID 7) เป็น NULL (ไม่มีข้อมูล) ซึ่งจุดนี้จะส่งผลกับการทำงานของ COUNT() ในภายหลัง
[พื้นฐาน 1] นับจำนวนเรคคอร์ดทั้งหมดด้วย `COUNT(*)`
มาเริ่มจากการใช้งานที่ง่ายที่สุด คือ COUNT(*) เครื่องหมายดอกจัน (*) หมายถึง “ทุกคอลัมน์” และ COUNT(*) จะคืนค่าจำนวนแถวทั้งหมดในตาราง ใช้เมื่อต้องการรู้ว่า “มีข้อมูลทั้งหมดกี่รายการ?”
ลองนับจำนวนผู้ใช้ทั้งหมดจากตาราง users
SELECT COUNT(*) FROM users;
ผลลัพธ์:
7
เราใส่ข้อมูลไว้ 7 รายการ ผลลัพธ์จึงเป็น “7” ซึ่งถูกต้อง นี่คือพื้นฐานของการใช้ COUNT()
[พื้นฐาน 2] ระบุคอลัมน์เพื่อให้นับเฉพาะ `COUNT(column_name)`
ถัดมาเราจะดูการใช้ COUNT(column_name) ซึ่งเป็นการนับจำนวนแถวที่มี “ข้อมูลอยู่” ในคอลัมน์ที่ระบุ
จุดสำคัญคือ COUNT(column_name) จะไม่นับค่าที่เป็น NULL กล่าวคือ แถวที่ไม่มีข้อมูลในคอลัมน์นั้นจะไม่ถูกนับ
ลองนับจำนวนผู้ใช้ที่มีอีเมลในตาราง users
SELECT COUNT(email) FROM users;
ผลลัพธ์:
5
ผลลัพธ์คือ “5” ซึ่งน้อยกว่าค่า “7” ของ COUNT(*) เพราะ Sato และ Tanaka มีค่า NULL ในคอลัมน์ email และจึงไม่ถูกนับ
จำให้แม่นว่า COUNT(*) คือจำนวนแถวทั้งหมด ส่วน COUNT(column_name) คือนับเฉพาะแถวที่มีข้อมูลในคอลัมน์นั้น
[ขั้นสูง 1] ตั้งชื่อผลลัพธ์ด้วย `AS`
โดยปกติผลลัพธ์จาก COUNT() จะแสดงชื่อคอลัมน์เป็น COUNT(*) หรือ COUNT(email) ซึ่งอาจอ่านยาก
ในกรณีนี้สามารถใช้ AS เพื่อกำหนดชื่อคอลัมน์ใหม่ให้อ่านง่ายขึ้น
SELECT COUNT(*) AS total_users FROM users;
ผลลัพธ์:
total_users
-----------
7
ด้วยการใช้ AS total_users คอลัมน์ผลลัพธ์เปลี่ยนชื่อเป็น total_users ช่วยให้เข้าใจง่ายขึ้น และยังสามารถเข้าถึงผลลัพธ์ผ่านโค้ดได้สะดวก เช่น result['total_users']
[ขั้นสูง 2] นับเฉพาะค่าที่ไม่ซ้ำด้วย `COUNT(DISTINCT column_name)`
ต่อไปคือ COUNT(DISTINCT) ซึ่งใช้บ่อยมากในการวิเคราะห์เว็บไซต์ คำสั่ง DISTINCT มีความหมายว่า “ตัดค่าที่ซ้ำกันออก” ทำให้สามารถนับจำนวนค่าที่ไม่ซ้ำได้
เช่น “มีผู้ใช้งานมาจากจังหวัดทั้งหมดกี่จังหวัด?”
ในตาราง users มีผู้ใช้จาก Tokyo 3 คน, Osaka 2 คน มาลองนับจำนวนจังหวัดที่ไม่ซ้ำกัน
SELECT COUNT(DISTINCT prefecture) AS unique_prefectures FROM users;
ผลลัพธ์:
unique_prefectures
------------------
4
ผลลัพธ์คือ “4” เพราะมี Tokyo, Osaka, Fukuoka และ Hokkaido รวม 4 จังหวัดที่ไม่ซ้ำกัน
ประโยชน์ของคำสั่งนี้มีมาก เช่น ใช้กับเว็บไซต์ร้านค้าเพื่อนับจำนวนหมวดหมู่สินค้า หรือดูจำนวนผู้เยี่ยมชมที่ไม่ซ้ำกันจาก log การเข้าถึง
[ขั้นสูง 3] นับแยกตามกลุ่มด้วย `GROUP BY`
COUNT() จะมีประสิทธิภาพสูงสุดเมื่อใช้งานร่วมกับคำสั่ง GROUP BY ซึ่งใช้จัดกลุ่มแถวที่มีค่าคอลัมน์เดียวกัน จากนั้นใช้ COUNT() กับแต่ละกลุ่มได้
เช่น “อยากรู้จำนวนผู้ใช้ในแต่ละจังหวัด” — นี่แหละเวลาที่ GROUP BY เหมาะสมที่สุด
SELECT
prefecture,
COUNT(*) AS user_count
FROM
users
GROUP BY
prefecture;
ผลลัพธ์:
prefecture | user_count
-----------|------------
Osaka | 2
Hokkaido | 1
Tokyo | 3
Fukuoka | 1
ยอดเยี่ยม! เราได้รายการจำนวนผู้ใช้แยกตามจังหวัด โดยใช้ prefecture เพื่อจัดกลุ่ม และ COUNT(*) เพื่อนับจำนวนแถวในแต่ละกลุ่ม
เทคนิคนี้มีความสำคัญมากในการวิเคราะห์ข้อมูล เช่น ตรวจสอบว่าผู้ใช้ส่วนใหญ่มาจากภูมิภาคใด
[ระดับโปร] กำหนดเงื่อนไขกับผลรวมด้วย `HAVING`
บางครั้งคุณอาจต้องการกรองผลลัพธ์หลังจากใช้ GROUP BY เช่น “แสดงเฉพาะจังหวัดที่มีผู้ใช้อย่างน้อย 2 คน”
ข้อน่าสังเกตคือ คำสั่ง WHERE ใช้กรองข้อมูลก่อนการจัดกลุ่ม ดังนั้นจะใช้ไม่ได้กับค่าผลรวม เช่น user_count
หากต้องการกรองหลังจากจัดกลุ่ม ต้องใช้คำสั่ง HAVING
SELECT
prefecture,
COUNT(*) AS user_count
FROM
users
GROUP BY
prefecture
HAVING
user_count >= 2;
ผลลัพธ์:
prefecture | user_count
-----------|------------
Osaka | 2
Tokyo | 3
เมื่อเพิ่มเงื่อนไข HAVING user_count >= 2 เราจะได้เฉพาะจังหวัดที่มีผู้ใช้อย่างน้อย 2 คน คือ Osaka และ Tokyo
จำไว้ว่า WHERE ใช้กับแถวก่อนการจัดกลุ่ม ส่วน HAVING ใช้กับผลลัพธ์หลังการจัดกลุ่มด้วย GROUP BY
[มุมโต้ตอบ] ลองรัน SQL ในเบราว์เซอร์ของคุณ!
ขอบคุณที่รอ! เราได้จัดเตรียมสภาพแวดล้อมที่คุณสามารถรัน SQL ที่เรียนรู้มาด้วยมือของคุณเองแล้ว
คัดลอกโค้ด HTML ทั้งหมดด้านล่าง บันทึกเป็นไฟล์ชื่อเช่น sql_test.html และเปิดในเบราว์เซอร์ของคุณ ตาราง users ที่นำเสนอในบทความนี้ถูกเตรียมไว้แล้ว ลองใช้คำสั่ง SQL หลายๆ แบบและดูผลลัพธ์ที่เปลี่ยนแปลง!
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>สภาพแวดล้อมรัน SQL สำหรับ COUNT()</title>
<style>
body { font-family: sans-serif; line-height: 1.6; color: #333; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
h1 { color: #444; }
textarea { width: 100%; height: 150px; font-family: monospace; font-size: 16px; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-bottom: 1rem; }
button { background-color: #007bff; color: white; border: none; padding: 10px 20px; font-size: 16px; border-radius: 4px; cursor: pointer; }
button:hover { background-color: #0056b3; }
button:disabled { background-color: #ccc; cursor: not-allowed; }
#result-container { margin-top: 2rem; border: 1px solid #ddd; padding: 1rem; border-radius: 4px; background: #f9f9f9; min-height: 50px; }
#error-message { color: #d9534f; font-weight: bold; }
table { border-collapse: collapse; width: 100%; margin-top: 1rem; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js"></script>
</head>
<body>
<h1>ลองใช้ SQL!</h1>
<p>ป้อน SQL ในช่องข้อความด้านล่างแล้วคลิกปุ่ม "รัน" ทดลองตัวอย่าง SQL ต่างๆ ที่นำเสนอในบทความนี้ได้เลย!</p>
<textarea id="sql-input">SELECT prefecture, COUNT(*) AS user_count
FROM users
GROUP BY prefecture
HAVING user_count >= 2;</textarea>
<button id="execute-btn">รัน</button>
<div id="result-container">
<p id="error-message"></p>
<div id="result-output"></div>
</div>
<script>
const sqlInput = document.getElementById('sql-input');
const executeBtn = document.getElementById('execute-btn');
const errorMsg = document.getElementById('error-message');
const resultOutput = document.getElementById('result-output');
let db;
async function initDb() {
executeBtn.disabled = true;
executeBtn.textContent = 'กำลังเตรียม...';
try {
const SQL = await initSqlJs({
locateFile: file => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/${file}`
});
db = new SQL.Database();
// ตั้งค่าตารางเริ่มต้นและข้อมูล
const setupSql = `
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
prefecture TEXT NOT NULL,
email TEXT
);
INSERT INTO users (id, name, prefecture, email) VALUES
(1, 'Taro Yamada', 'Tokyo', 'yamada@example.com'),
(2, 'Hanako Suzuki', 'Osaka', 'suzuki@example.com'),
(3, 'Jiro Sato', 'Tokyo', NULL),
(4, 'Sakura Ito', 'Fukuoka', 'ito@example.com'),
(5, 'Saburo Watanabe', 'Hokkaido', 'watanabe@example.com'),
(6, 'Shiro Takahashi', 'Tokyo', 'takahashi@example.com'),
(7, 'Misaki Tanaka', 'Osaka', NULL);
`;
db.run(setupSql);
executeBtn.disabled = false;
executeBtn.textContent = 'รัน';
resultOutput.innerHTML = '<p>พร้อมแล้ว! ป้อน SQL ของคุณและคลิก รัน ได้เลย</p>';
} catch (err) {
errorMsg.textContent = 'ไม่สามารถเตรียมฐานข้อมูลได้: ' + err.message;
console.error(err);
}
}
function executeSql() {
if (!db) return;
const sql = sqlInput.value;
errorMsg.textContent = '';
resultOutput.innerHTML = '';
try {
const results = db.exec(sql);
if (results.length === 0) {
resultOutput.innerHTML = '<p>คิวรีสำเร็จ แต่ไม่มีชุดผลลัพธ์ส่งกลับ (เช่น INSERT, UPDATE ฯลฯ)</p>';
return;
}
results.forEach(result => {
const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
const headerRow = document.createElement('tr');
result.columns.forEach(colName => {
const th = document.createElement('th');
th.textContent = colName;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
result.values.forEach(row => {
const bodyRow = document.createElement('tr');
row.forEach(cellValue => {
const td = document.createElement('td');
td.textContent = cellValue === null ? 'NULL' : cellValue;
bodyRow.appendChild(td);
});
tbody.appendChild(bodyRow);
});
table.appendChild(thead);
table.appendChild(tbody);
resultOutput.appendChild(table);
});
} catch (err) {
errorMsg.textContent = 'ข้อผิดพลาดของ SQL: ' + err.message;
console.error(err);
}
}
executeBtn.addEventListener('click', executeSql);
initDb();
</script>
</body>
</html>
【ลองใช้งานกันเถอะ!】
- ลองนับจำนวนผู้ใช้ที่ไม่มีอีเมลลงทะเบียนไว้ (คำใบ้: ความแตกต่างระหว่าง
COUNT(*)กับCOUNT(email)) - ลองนับเฉพาะผู้ใช้ที่มีภูมิลำเนาเป็น “โตเกียว” (คำใบ้: ใช้คำสั่ง
WHERE) - ลองเขียนคำสั่ง
INSERTเพื่อเพิ่มข้อมูลใหม่ แล้วใช้COUNT(*)เพื่อตรวจสอบว่าจำนวนเพิ่มขึ้นหรือไม่
จุดที่ควรระวังและเกร็ดความรู้
COUNT(*)vsCOUNT(1)vsCOUNT(column_name)-
บางครั้งจะเห็นรูปแบบ
COUNT(1)ซึ่งหมายความว่ามีการกำหนดค่า “1” ให้แต่ละแถว แล้วนับจำนวนของค่านั้น ในฐานข้อมูลส่วนใหญ่COUNT(*)และCOUNT(1)จะให้ผลลัพธ์และประสิทธิภาพเหมือนกัน เพราะทั้งสองนับทุกแถว ส่วนCOUNT(column_name)จะไม่นับค่าNULLตามที่อธิบายไว้ก่อนหน้านี้ จึงใช้ในวัตถุประสงค์ที่ต่างกัน หากไม่แน่ใจ ให้ใช้COUNT(*)หากต้องการนับทุกแถว หรือCOUNT(column_name)หากต้องการนับเฉพาะค่าที่ไม่เป็น NULL - ประสิทธิภาพ
-
หากใช้
COUNT(*)กับตารางขนาดใหญ่ที่มีหลายล้านแถว อาจใช้เวลานาน โดยเฉพาะเมื่อไม่มีเงื่อนไขใดๆ เพราะจะต้องสแกนข้อมูลทั้งหมด หากจำเป็นต้องนับจำนวนรวมบ่อยๆ อาจพิจารณาวิธีอื่น เช่น การสร้างตารางสรุปข้อมูล แต่ในเบื้องต้นเพียงแค่รู้วิธีใช้งานพื้นฐานก็เพียงพอ
ฟังก์ชันที่เกี่ยวข้อง: ฟังก์ชันการรวมอื่นๆ
เมื่อเข้าใจ COUNT() แล้ว ฟังก์ชันการรวมอื่นๆ ก็สามารถเรียนรู้ได้ง่ายเช่นกัน โดยจะทรงพลังมากเมื่อใช้ร่วมกับ GROUP BY
SUM(column_name): คำนวณผลรวมของค่าตัวเลขในคอลัมน์ (เช่น ยอดขายรวม)AVG(column_name): คำนวณค่าเฉลี่ยของค่าตัวเลขในคอลัมน์ (เช่น อายุเฉลี่ย ราคาขายเฉลี่ย)MAX(column_name): ดึงค่าที่มากที่สุดจากคอลัมน์ (เช่น อุณหภูมิสูงสุด คะแนนสูงสุด)MIN(column_name): ดึงค่าที่น้อยที่สุดจากคอลัมน์ (เช่น ราคาต่ำสุด)
ตัวอย่างเช่น หากต้องการทราบรหัสผู้ใช้ที่มากที่สุด ให้ใช้โค้ดนี้:
SELECT MAX(id) AS latest_user_id FROM users;
สรุป
บทความนี้ได้แนะนำการใช้ฟังก์ชัน COUNT() ตั้งแต่พื้นฐานจนถึงการประยุกต์ใช้งานในเชิงลึก
COUNT(*): นับจำนวนแถวทั้งหมดในตารางCOUNT(column_name): นับเฉพาะแถวที่ไม่เป็นNULLในคอลัมน์ที่ระบุCOUNT(DISTINCT column_name): นับเฉพาะค่าที่ไม่ซ้ำกันAS alias: ตั้งชื่อลัดให้กับคอลัมน์ผลลัพธ์GROUP BY: ใช้กับCOUNT()เพื่อสรุปผลแบบกลุ่ม
COUNT() เป็นจุดเริ่มต้นที่สำคัญในการวิเคราะห์ข้อมูล ลองเล่นกับตัวอย่างโค้ดในบทความให้บ่อยๆ แล้วคุณจะเข้าใจการ “นับข้อมูล” ได้ชัดเจนยิ่งขึ้น เมื่อคุณใช้ SQL ได้คล่อง จะสามารถเปิดโลกใหม่ของการวิเคราะห์ข้อมูลได้เลย สนุกกับการเรียนรู้ต่อไปนะครับ!