🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

มาทำความเข้าใจ SQL HAVING Clause: การเจาะลึกเพื่อกรองข้อมูลที่จัดกลุ่มแล้ว

เมื่อคุณคุ้นเคยกับคำสั่ง GROUP BY ของ SQL แล้ว คุณจะสามารถทำการรวมข้อมูลที่มีประโยชน์ได้ เช่น การนับจำนวนสินค้าตามหมวดหมู่ หรือจำนวนคำสั่งซื้อของลูกค้าแต่ละราย แต่การวิเคราะห์ข้อมูลที่แท้จริงเริ่มต้นจากจุดนั้น คุณจะต้องพบกับสถานการณ์ที่คุณต้องการกรองข้อมูลเพิ่มเติมจากผลลัพธ์ที่รวมไว้นั้นอย่างแน่นอน โดยอาจมีคำถามเช่น "ใครคือลูกค้ายอดเยี่ยมของเราที่มีคำสั่งซื้อมากที่สุด?" หรือ "หมวดหมู่สินค้ายอดนิยมใดที่มีราคาสูงสุดโดยเฉลี่ย?"

คำตอบสำหรับ "การกรองข้อมูลหลังการจัดกลุ่ม" นี้คือหัวข้อหลักของเราในวันนี้: คำสั่ง HAVING เมื่อใช้ร่วมกับ GROUP BY คำสั่ง HAVING จะช่วยเพิ่มความแม่นยำและความลึกของการวิเคราะห์ข้อมูลของคุณได้อย่างมาก มันเป็นเครื่องมือที่สมบูรณ์แบบที่ตอบโจทย์ความต้องการของคุณได้อย่างตรงจุด

บทความนี้จะอธิบายบทบาทและการใช้งานของคำสั่ง HAVING อย่างละเอียดตั้งแต่ต้น โดยเน้นที่ความแตกต่างจากคำสั่ง WHERE ซึ่งเป็นจุดที่ผู้เรียน SQL หลายคนสับสน ผ่านตัวอย่าง "คัดลอก-วาง-และรัน" จำนวนมาก (พร้อมสภาพแวดล้อม SQL ออนไลน์!) คุณจะได้สัมผัสกับช่วงเวลาที่ "อ๋อ!" และได้ประสบการณ์ตรงว่ามันทำงานอย่างไร ซึ่งจะยกระดับทักษะการรวมข้อมูลของคุณไปอีกขั้น!


การเตรียมตัว: มาสร้างข้อมูลตัวอย่างสำหรับคำสั่งซื้อกัน

ก่อนที่จะลงลึกในทฤษฎี เรามาสร้างพื้นฐานที่นำไปใช้ได้จริงกันก่อน เราจะใช้ตาราง orders ที่จำลองประวัติการสั่งซื้อของเว็บไซต์อีคอมเมิร์ซ ซึ่งประกอบด้วยข้อมูลที่ใช้งานได้จริง เช่น ID ลูกค้า, หมวดหมู่สินค้า, ราคา และวันที่สั่งซื้อ คุณสามารถคัดลอกคำสั่ง SQL ทั้งหมดด้านล่างเพื่อรันในสภาพแวดล้อมของคุณเอง หรือใช้ในส่วน "สนามเด็กเล่นแบบโต้ตอบ" ในภายหลัง

-- ลบตารางถ้ามีอยู่แล้ว (เพื่อให้สามารถทดสอบซ้ำได้)
DROP TABLE IF EXISTS orders;

-- สร้างตาราง orders
CREATE TABLE orders (
  order_id INTEGER PRIMARY KEY,
  customer_id INTEGER NOT NULL,
  product_category TEXT NOT NULL,
  price INTEGER NOT NULL,
  order_date DATE NOT NULL
);

-- เพิ่มข้อมูล
INSERT INTO orders (order_id, customer_id, product_category, price, order_date) VALUES
(1, 101, 'อุปกรณ์คอมพิวเตอร์', 15000, '2025-05-10'),
(2, 102, 'หนังสือ', 3200, '2025-05-11'),
(3, 101, 'อุปกรณ์คอมพิวเตอร์', 250000, '2025-05-12'),
(4, 103, 'เครื่องใช้ไฟฟ้า', 88000, '2025-05-15'),
(5, 102, 'หนังสือ', 4500, '2025-05-20'),
(6, 101, 'เครื่องใช้ไฟฟ้า', 120000, '2025-06-01'),
(7, 104, 'อุปกรณ์คอมพิวเตอร์', 8000, '2025-06-05'),
(8, 102, 'เสื้อผ้า', 7800, '2025-06-08'),
(9, 103, 'อุปกรณ์คอมพิวเตอร์', 320000, '2025-06-10'),
(10, 105, 'หนังสือ', 2900, '2025-06-15'),
(11, 101, 'หนังสือ', 3500, '2025-06-20'),
(12, 103, 'เครื่องใช้ไฟฟ้า', 35000, '2025-06-22');

ข้อมูลนี้มีลูกค้าที่ทำการซื้อหลายครั้ง (เช่น ID ลูกค้า 101, 102, 103) และหมวดหมู่ที่ถูกซื้อโดยลูกค้าหลายราย (เช่น อุปกรณ์คอมพิวเตอร์, หนังสือ) ซึ่งเหมาะอย่างยิ่งสำหรับการสังเกตพฤติกรรมของ GROUP BY และ HAVING


แนวคิดหลัก: ความแตกต่างที่ชัดเจนระหว่าง WHERE และ HAVING

กุญแจสำคัญที่สุดในการทำความเข้าใจคำสั่ง HAVING คือการเข้าใจการแบ่งหน้าที่ของมันกับคำสั่ง WHERE อย่างชัดเจน แม้ว่าทั้งสองจะใช้สำหรับ "การกรอง" แต่เวลาและเป้าหมายในการกรองของพวกมันนั้นแตกต่างกันโดยสิ้นเชิง

ลองมาดูความแตกต่างนี้โดยใช้การเปรียบเทียบกับห้องครัวของร้านอาหาร

ลำดับการทำงานของ SQL: การเปรียบเทียบกับร้านอาหาร

  1. การรวมตาราง (FROM, JOIN): ก่อนอื่น วัตถุดิบทั้งหมด (ข้อมูล) จะถูกรวบรวมไว้ในครัว
  2. คำสั่ง WHERE: เชฟเข้ามา ก่อนเริ่มทำอาหาร เชฟจะตรวจสอบวัตถุดิบแต่ละชิ้นและคัดแยกสิ่งที่ไม่ตรงตามเกณฑ์ออกไป โดยพูดว่า "ฉันไม่สามารถใช้ปลานี้สำหรับคาร์ปาชโชวันนี้ได้"
  3. คำสั่ง GROUP BY: เชฟใช้วัตถุดิบที่ผ่านการคัดเลือกแล้วมาทำอาหารหลากหลายเมนู (กลุ่ม) เช่น สลัด, พาสต้า และอาหารจานหลัก
  4. คำสั่ง HAVING: นักวิจารณ์อาหารเข้ามา เมื่ออาหารที่ทำเสร็จแล้ว (กลุ่ม) ถูกจัดวางบนโต๊ะ นักวิจารณ์จะตัดสินใจว่าจะประเมินจานไหน โดยพูดว่า "ฉันจะชิมเฉพาะอาหารที่มีราคามากกว่า $20 เท่านั้น"

จากการเปรียบเทียบนี้ สิ่งสำคัญสองประการที่เราได้เรียนรู้คือ:

ด้วยเหตุนี้ เงื่อนไขที่ใช้ฟังก์ชันการรวมข้อมูลเช่น COUNT() หรือ SUM() จึงมีความหมายสำหรับกลุ่มเท่านั้น และดังนั้นจึงสามารถใช้ได้เฉพาะในคำสั่ง HAVING คุณไม่สามารถเขียนโค้ดอย่าง WHERE COUNT(*) > 10 ได้


ในการปฏิบัติ: การกรองผลลัพธ์ที่รวมไว้ด้วยคำสั่ง HAVING

ตอนนี้ เรามาดูพลังของคำสั่ง HAVING ในการใช้งานจริงกันก่อนอื่น เราจะใช้ GROUP BY เพื่อรวม "จำนวนคำสั่งซื้อของลูกค้าแต่ละราย" นี่จะเป็นผลลัพธ์พื้นฐานของเราก่อนที่จะใช้คำสั่ง HAVING

-- ก่อนอื่น มานับจำนวนคำสั่งซื้อของลูกค้าแต่ละรายโดยไม่ใช้ HAVING
SELECT
  customer_id,
  COUNT(order_id) AS order_count
FROM
  orders
GROUP BY
  customer_id;

ผลลัพธ์:

customer_id | order_count
------------|-------------
101         | 4
102         | 3
103         | 3
104         | 1
105         | 1

จากผลลัพธ์นี้ สมมติว่าเราต้องการ "ดึงเฉพาะลูกค้ายอดเยี่ยมของเราที่มีคำสั่งซื้อ 3 รายการขึ้นไป" นี่คือจุดที่คำสั่ง HAVING เข้ามามีบทบาท เราจะใช้เงื่อนไขกับผลลัพธ์ที่รวมไว้ นั่นคือ `order_count` (ซึ่งก็คือ COUNT(order_id))

-- 【HAVING + COUNT】กรองลูกค้าที่มีคำสั่งซื้อ 3 รายการขึ้นไป
SELECT
  customer_id,
  COUNT(order_id) AS order_count
FROM
  orders
GROUP BY
  customer_id
HAVING
  COUNT(order_id) >= 3;

ผลลัพธ์:

customer_id | order_count
------------|-------------
101         | 4
102         | 3
103         | 3

ยอดเยี่ยม! เฉพาะลูกค้าที่มีคำสั่งซื้อ 3 รายการขึ้นไป (HAVING COUNT(order_id) >= 3) เท่านั้นที่ถูกกรองออกมา นี่คือการใช้งานพื้นฐานของคำสั่ง HAVING


ตัวอย่างขั้นสูง: เงื่อนไขด้วย `SUM` และ `AVG`

คำสั่ง HAVING ไม่ได้จำกัดอยู่แค่ COUNT แน่นอนว่ามันสามารถใช้ร่วมกับฟังก์ชันการรวมข้อมูลอื่นๆ ได้ เช่น SUM (ผลรวม) และ AVG (ค่าเฉลี่ย) ซึ่งช่วยให้สามารถวิเคราะห์ข้อมูลที่ซับซ้อนยิ่งขึ้นได้

【HAVING + SUM】การกรองหมวดหมู่ที่มียอดขายรวมเกิน 100,000

เพื่อค้นหาว่า "หมวดหมู่ใดที่สร้างรายได้ให้เรามากที่สุด" เราจะคำนวณยอดขายรวมของแต่ละหมวดหมู่แล้วดูเฉพาะหมวดหมู่ที่มียอดขายเกิน 100,000

-- 【HAVING + SUM】กรองหมวดหมู่ที่มียอดขายรวมเกิน 100,000
SELECT
  product_category,
  SUM(price) AS total_sales
FROM
  orders
GROUP BY
  product_category
HAVING
  SUM(price) > 100000;

ผลลัพธ์:

product_category   | total_sales
--------------------|-------------
อุปกรณ์คอมพิวเตอร์     | 593000
เครื่องใช้ไฟฟ้า      | 243000

ผลลัพธ์นี้ทำให้เห็นชัดเจนว่า "อุปกรณ์คอมพิวเตอร์" และ "เครื่องใช้ไฟฟ้า" เป็นแหล่งรายได้หลัก


【HAVING + AVG】การกรองหมวดหมู่ที่มีราคาเฉลี่ยเกิน 50,000

ต่อไป เพื่อตรวจสอบว่า "หมวดหมู่ใดที่ขายสินค้าราคาสูง" เราจะคำนวณราคาเฉลี่ยของแต่ละหมวดหมู่และดึงเฉพาะหมวดหมู่ที่มีค่าเฉลี่ยเกิน 50,000

-- 【HAVING + AVG】กรองหมวดหมู่ที่มีราคาเฉลี่ยเกิน 50,000
SELECT
  product_category,
  AVG(price) AS average_price
FROM
  orders
GROUP BY
  product_category
HAVING
  AVG(price) > 50000;

ผลลัพธ์:

product_category   | average_price
--------------------|---------------
อุปกรณ์คอมพิวเตอร์     | 148250
เครื่องใช้ไฟฟ้า      | 81000

อย่างที่คุณเห็น เราสามารถประเมินหมวดหมู่จากมุมมองที่แตกต่างกัน ไม่ใช่แค่ยอดขายรวม แต่ยังรวมถึงราคาเฉลี่ยด้วย


การผสมผสานขั้นสุดยอด: การใช้ WHERE และ HAVING ร่วมกัน

WHERE และ HAVING ไม่ใช่คู่แข่งกัน แต่เป็นพันธมิตรที่ทำงานร่วมกันเพื่อให้ได้การกรองที่ซับซ้อนยิ่งขึ้น การใช้ทั้งสองอย่างในคำสั่งเดียวช่วยให้สามารถวิเคราะห์ข้อมูลได้อย่างทรงพลังอย่างไม่น่าเชื่อ

คำถามในการวิเคราะห์ของเรา: "เมื่อดูเฉพาะคำสั่งซื้อตั้งแต่เดือนมิถุนายน 2025 เป็นต้นไป ใครคือลูกค้าที่มียอดซื้อรวมเกิน 100,000?"

ถ้าเราแยกย่อยคำขอนี้ เราจะเห็นว่ามีขั้นตอนการกรองสองขั้นตอน:

  1. การกรองก่อนการจัดกลุ่ม: จำกัดระเบียนข้อมูลเฉพาะคำสั่งซื้อตั้งแต่วันที่ 1 มิถุนายน 2025 เป็นต้นไป → นี่เป็นเงื่อนไขสำหรับระเบียนข้อมูลแต่ละรายการ ดังนั้นจึงเป็นหน้าที่ของคำสั่ง WHERE
  2. การกรองหลังการจัดกลุ่ม: จำกัดกลุ่มเฉพาะลูกค้าที่มียอดซื้อรวมที่ถูกรวมแล้วมากกว่า 100,000 → นี่เป็นเงื่อนไขสำหรับกลุ่ม ดังนั้นจึงเป็นหน้าที่ของคำสั่ง HAVING

นี่คือคำสั่ง SQL ที่สอดคล้องกัน:

-- 【WHERE + HAVING】ลูกค้าที่มียอดซื้อรวม > 100k ตั้งแต่เดือนมิถุนายนเป็นต้นไป
SELECT
  customer_id,
  SUM(price) AS total_spent_in_june_onwards
FROM
  orders
WHERE
  order_date >= '2025-06-01'
GROUP BY
  customer_id
HAVING
  SUM(price) > 100000;

ผลลัพธ์:

customer_id | total_spent_in_june_onwards
------------|-----------------------------
101         | 123500
103         | 355000

ขั้นตอนการประมวลผลของคำสั่งนี้ตรงกับการเปรียบเทียบร้านอาหารของเราอย่างสมบูรณ์แบบ:

  1. ก่อนอื่น WHERE order_date >= '2025-06-01' จะเลือกระเบียนคำสั่งซื้อตั้งแต่เดือนมิถุนายนเป็นต้นไป
  2. จากนั้น ระเบียนที่ถูกเลือกเหล่านี้จะถูกจัดกลุ่มตามลูกค้าโดยใช้ GROUP BY customer_id
  3. สุดท้าย HAVING SUM(price) > 100000 จะกรองกลุ่มเหล่านี้ โดยเก็บไว้เฉพาะกลุ่มที่ยอดซื้อรวมเกิน 100,000

ความร่วมมือระหว่าง WHERE และ HAVING นี้อาจกล่าวได้ว่าเป็นจุดที่ SQL โดดเด่นที่สุดในการวิเคราะห์ข้อมูล


【สนามเด็กเล่นแบบโต้ตอบ】SQL Fiddle: ลองใช้คำสั่ง HAVING ในเบราว์เซอร์ของคุณ!

ตอนนี้ถึงเวลาเปลี่ยนความรู้ให้เป็นทักษะที่แข็งแกร่ง! ด้วย "สภาพแวดล้อม SQL ออนไลน์" ด้านล่าง คุณสามารถทดลองใช้ SQL ได้อย่างอิสระในเบราว์เซอร์ของคุณ ตาราง orders จากบทความนี้ได้ถูกโหลดไว้ให้คุณแล้ว

ลองใช้เงื่อนไขต่างๆ การเปลี่ยนตัวเลขง่ายๆ หรือสลับ >= กับ < จะแสดงให้คุณเห็นว่าผลลัพธ์เปลี่ยนแปลงอย่างไร และจะช่วยให้คุณเข้าใจลึกซึ้งยิ่งขึ้นอย่างมาก

<!DOCTYPE html>
<html lang="th">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>สนามเด็กเล่นออนไลน์สำหรับ SQL HAVING Clause</title>
  <style>
    body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.7; color: #333; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
    h1 { color: #2c3e50; }
    textarea { width: 100%; height: 200px; font-family: "SF Mono", "Consolas", monospace; font-size: 16px; padding: 12px; border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box; margin-bottom: 1rem; }
    button { background-color: #8e44ad; color: white; border: none; padding: 12px 22px; font-size: 16px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; }
    button:hover { background-color: #70368b; }
    button:disabled { background-color: #bdc3c7; cursor: not-allowed; }
    #result-container { margin-top: 2rem; border: 1px solid #ddd; padding: 1rem; border-radius: 6px; background: #fdfdfd; min-height: 50px; overflow-x: auto;}
    #error-message { color: #e74c3c; font-weight: bold; }
    table { border-collapse: collapse; width: 100%; margin-top: 1rem; }
    th, td { border: 1px solid #ddd; padding: 10px; text-align: left; white-space: nowrap; }
    th { background-color: #f2f2f2; }
    tr:nth-child(even) { background-color: #f9f9f9; }
  </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 ของคุณในช่องข้อความด้านล่างแล้วคลิกปุ่ม "Execute" คุณสามารถลองใช้คำสั่งต่างๆ จากบทความได้เลย!</p>

  <textarea id="sql-input">-- ลองทดลองได้ตามสบาย!
-- ตัวอย่าง: กรองเฉพาะหมวดหมู่ 'อุปกรณ์คอมพิวเตอร์' (WHERE),
--          จากนั้นคำนวณยอดใช้จ่ายรวมของลูกค้าแต่ละราย (GROUP BY),
--          และสุดท้าย แสดงเฉพาะลูกค้าที่ใช้จ่ายเกิน 200,000 (HAVING)
SELECT
  customer_id,
  SUM(price) AS total_spent_on_pc
FROM
  orders
WHERE
  product_category = 'อุปกรณ์คอมพิวเตอร์'
GROUP BY
  customer_id
HAVING
  SUM(price) > 200000;</textarea>
  
  <button id="execute-btn">Execute</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 orders;
          CREATE TABLE orders (
            order_id INTEGER PRIMARY KEY,
            customer_id INTEGER NOT NULL,
            product_category TEXT NOT NULL,
            price INTEGER NOT NULL,
            order_date DATE NOT NULL
          );
          INSERT INTO orders (order_id, customer_id, product_category, price, order_date) VALUES
          (1, 101, 'อุปกรณ์คอมพิวเตอร์', 15000, '2025-05-10'), (2, 102, 'หนังสือ', 3200, '2025-05-11'),
          (3, 101, 'อุปกรณ์คอมพิวเตอร์', 250000, '2025-05-12'), (4, 103, 'เครื่องใช้ไฟฟ้า', 88000, '2025-05-15'),
          (5, 102, 'หนังสือ', 4500, '2025-05-20'), (6, 101, 'เครื่องใช้ไฟฟ้า', 120000, '2025-06-01'),
          (7, 104, 'อุปกรณ์คอมพิวเตอร์', 8000, '2025-06-05'), (8, 102, 'เสื้อผ้า', 7800, '2025-06-08'),
          (9, 103, 'อุปกรณ์คอมพิวเตอร์', 320000, '2025-06-10'), (10, 105, 'หนังสือ', 2900, '2025-06-15'),
          (11, 101, 'หนังสือ', 3500, '2025-06-20'), (12, 103, 'เครื่องใช้ไฟฟ้า', 35000, '2025-06-22');
        `;
        db.run(setupSql);
        
        executeBtn.disabled = false;
        executeBtn.textContent = 'Execute';
        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, etc.)</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' : (typeof cellValue === 'number' ? cellValue.toLocaleString() : 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>

เบื้องหลังของ SQL Engine: ลำดับการประมวลผลคำสั่งเชิงตรรกะ

เพื่อทำความเข้าใจความแตกต่างระหว่าง WHERE และ HAVING ให้ลึกซึ้งยิ่งขึ้น การรู้ "ลำดับการประมวลผลเชิงตรรกะ" ของวิธีที่ SQL จัดการกับคำสั่งภายในนั้นมีประโยชน์อย่างยิ่ง ลำดับที่เราเขียนโค้ด (SELECT, FROM, WHERE...) แตกต่างจากลำดับที่ SQL ตีความและดำเนินการ

ลำดับการดำเนินการเชิงตรรกะของ SQL:

  1. FROM: ก่อนอื่น กำหนดว่าจะดึงข้อมูลจากตารางใด
  2. WHERE: จากนั้น กรองระเบียนข้อมูลแต่ละรายการตามเงื่อนไข
  3. GROUP BY: รวมระเบียนที่กรองแล้วเป็นกลุ่ม
  4. HAVING: กรองผลลัพธ์ที่จัดกลุ่มแล้วตามเงื่อนไข
  5. SELECT: สุดท้าย ตัดสินใจว่าจะแสดงคอลัมน์ใด
  6. ORDER BY: เรียงลำดับชุดผลลัพธ์ตามลำดับที่กำหนด
  7. LIMIT: จำกัดจำนวนแถวที่จะแสดง

เมื่อดูลำดับนี้ คุณจะเห็นได้อย่างชัดเจนว่า WHERE มาก่อน GROUP BY และ HAVING มาทีหลัง นี่คือเหตุผลหลักว่าทำไมฟังก์ชันการรวมข้อมูลจึงไม่สามารถใช้ใน WHERE ได้ แต่สามารถใช้ใน HAVING ได้

ลำดับนี้ยังอธิบายได้ว่าทำไมโดยทั่วไปแล้วคุณไม่สามารถใช้ชื่อแฝง (alias) ที่กำหนดในคำสั่ง SELECT (เช่น SUM(price) AS total_sales) ในคำสั่ง WHERE หรือ HAVING ได้ (ยกเว้นบางฐานข้อมูล) นั่นเป็นเพราะคำสั่ง SELECT ถูกประเมินในภายหลัง (คุณมักจะสามารถใช้ชื่อแฝงในคำสั่ง ORDER BY ได้ เพราะ ORDER BY ถูกประเมินหลัง SELECT)


สรุป: มาเป็นผู้เชี่ยวชาญในคำสั่ง HAVING และยกระดับการวิเคราะห์ข้อมูลของคุณไปอีกขั้น

ในการเจาะลึกครั้งนี้ เราได้สำรวจคำสั่ง HAVING ที่ทรงพลัง ซึ่งเป็นเครื่องมือสำหรับกรองผลลัพธ์ของการรวมข้อมูลด้วย GROUP BY

เรามาทบทวนประเด็นสำคัญกันอีกครั้ง:

คำสั่ง HAVING อาจดูเหมือนเป็นฟีเจอร์เล็กๆ ในตอนแรก อย่างไรก็ตาม การที่คุณจะเชี่ยวชาญมันได้หรือไม่นั้นจะสร้างความแตกต่างอย่างมากในคุณภาพและความลึกของข้อมูลเชิงลึกที่คุณสามารถดึงออกมาจากข้อมูลของคุณได้ มันช่วยให้คุณสามารถตอบคำถามที่เฉียบคมและมีความสำคัญต่อธุรกิจมากขึ้นด้วย SQL เช่น "ในบรรดาหมวดหมู่ที่ขายดีที่สุดของเรา หมวดหมู่ใดที่ทำกำไรได้มากที่สุด?" หรือ "ในบรรดาฐานผู้ใช้งานที่ยังคงใช้งานอยู่ โปรไฟล์ของผู้ใช้ที่ใช้จ่ายสูงสุดคืออะไร?"

ขอให้คุณสนุกกับการเล่นในสนามเด็กเล่นออนไลน์จากบทความนี้และทำความคุ้นเคยกับคำสั่ง HAVING ฉันรับประกันว่าทักษะการใช้ข้อมูลของคุณในฐานะนักสร้างสรรค์เว็บจะพัฒนาขึ้นอย่างก้าวกระโดด