0Pricing
SQL Academy · บทเรียน

NULL ในการรวมค่าและการเชื่อมตาราง

NULL มีพฤติกรรมอย่างไรใน COUNT, SUM และ JOIN

NULL ในการรวมค่าและการเชื่อมตาราง เป็นบทเรียน SQL Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน

ค่า NULL เปลี่ยนผลการคำนวณ

ฟังก์ชันรวมและการ JOIN ต่างก็จัดการกับ NULL ในลักษณะพิเศษ หากคุณไม่ทราบกฎเหล่านี้ ยอดรวมและจำนวนอาจผิดพลาดโดยที่สังเกตได้ยาก

บทเรียนนี้แสดงให้เห็นว่า COUNT, SUM, AVG, GROUP BY และการ JOIN ภายนอกทำงานร่วมกับค่าที่หายไปอย่างไร

SELECT amount FROM payments;
-- amount
-- -------
--    100
--   NULL   <- missing
--    200

ฟังก์ชันรวมไม่สนใจค่า NULL

ฟังก์ชันรวมส่วนใหญ่ — SUM, AVG, MIN, MAX — จะข้ามค่า NULL ไป โดยรวมเฉพาะแถวที่มีข้อมูลเท่านั้น

ดังนั้น จำนวนเงินที่เป็น NULL จึงไม่ทำให้ SUM มีปัญหา แต่จะถูกไม่นำมารวมในยอดทั้งหมด

-- Using amounts 100, NULL, 200
SELECT
  SUM(amount) AS total,  -- 300 (NULL skipped)
  MIN(amount) AS lo,     -- 100
  MAX(amount) AS hi      -- 200
FROM payments;

AVG ก็ข้ามค่า NULL เช่นกัน

AVG หารผลรวมของค่าที่ไม่ใช่ NULLด้วยจำนวนค่าที่ไม่ใช่ NULL ค่า NULL จะถูกตัดออกจากทั้งสองส่วน

เรื่องนี้สำคัญ: ค่าเฉลี่ยของ {100, NULL, 200} คือ 150 ไม่ใช่ 100 — ค่า NULL ไม่ได้ถูกนับเป็นศูนย์

-- (100 + 200) / 2 = 150, the NULL row is ignored
SELECT AVG(amount) AS avg_amount FROM payments;

-- If you WANT NULLs counted as 0, COALESCE first:
SELECT AVG(COALESCE(amount, 0)) AS avg_with_zeros FROM payments; -- 100

COUNT(*) กับ COUNT(คอลัมน์)

ความแตกต่างนี้ทำให้หลายคนสับสน:

  • COUNT(*) นับแถว รวมถึงแถวที่มีค่า NULL
  • COUNT(column) นับเฉพาะแถวที่คอลัมน์นั้นไม่ใช่ NULL
-- 3 rows total, but only 2 have a non-NULL amount
SELECT
  COUNT(*)       AS row_count,    -- 3
  COUNT(amount)  AS has_amount    -- 2
FROM payments;

COUNT(DISTINCT) กับ NULL

COUNT(DISTINCT col) นับจำนวนค่าที่ไม่ใช่ NULL และแตกต่างกัน ค่า NULL จะถูกตัดออกทั้งหมด จึงไม่เพิ่มจำนวนค่าที่แตกต่างกัน

โปรดคำนึงถึงเรื่องนี้เมื่อวัดว่ามีรายการที่ไม่ซ้ำกันอยู่กี่รายการ

-- statuses: 'paid', NULL, 'paid', 'void'
SELECT COUNT(DISTINCT status) AS distinct_statuses
FROM payments;
-- 2  (paid, void) -- NULL not counted

ฟังก์ชันรวมกับชุดว่าง

เมื่อฟังก์ชันรวมทำงานกับศูนย์แถว ผลลัพธ์จะขึ้นอยู่กับฟังก์ชันนั้น:

  • COUNT(...) คืนค่า 0
  • SUM, AVG, MIN, MAX คืนค่า NULL

ใช้ COALESCE เพื่อเปลี่ยนผลรวมที่เป็น NULL ให้เป็น 0 เมื่อเหมาะสม

-- No rows match -> SUM is NULL, not 0
SELECT COALESCE(SUM(amount), 0) AS total
FROM payments
WHERE status = 'refunded';  -- no such rows

GROUP BY จัดกลุ่มค่า NULL ไว้ด้วยกัน

แม้ว่า NULL = NULL จะมีสถานะไม่ทราบค่าในบริบทอื่น แต่ GROUP BY จะจัดค่า NULL ทั้งหมดไว้ในกลุ่มเดียวกัน

ดังนั้น หมวดหมู่ที่เป็น NULL จะกลายเป็นกลุ่มของตัวเองในผลลัพธ์ ทำให้คุณสรุปแถวที่มีข้อมูลหายไปไว้ด้วยกันได้

SELECT category, COUNT(*) AS n
FROM products
GROUP BY category;

-- category | n
-- ---------+---
-- books    | 5
-- toys     | 3
-- NULL     | 2   <- all NULL categories in one group

ค่า NULL จากการ JOIN ภายนอก

การ JOIN ภายนอกเป็นแหล่งสำคัญของค่า NULL การใช้ LEFT JOIN จะเก็บแถวฝั่งซ้ายไว้ทุกแถว หากไม่มีแถวที่ตรงกันทางด้านขวา คอลัมน์ฝั่งขวาจะกลายเป็น NULL

ค่า NULL เหล่านี้หมายถึง “ไม่มีแถวที่ตรงกัน” ไม่ใช่ “ค่าที่จัดเก็บไว้เป็น NULL”

SELECT c.name, o.id AS order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;

-- name  | order_id
-- ------+---------
-- Alice | 10
-- Bob   | NULL     <- Bob has no orders

การนับรายการที่ตรงกันหลัง LEFT JOIN

หากต้องการนับเฉพาะรายการที่ตรงกันจริงหลังการ LEFT JOIN ให้นับคอลัมน์ที่ไม่เป็น NULL จากตารางฝั่งขวา ไม่ใช่ COUNT(*)

COUNT(o.id) จะไม่รวมแถว NULL ที่เกิดจากแถวฝั่งซ้ายซึ่งไม่มีรายการตรงกัน จึงให้จำนวนคำสั่งซื้อที่แท้จริง

SELECT c.name, COUNT(o.id) AS order_count
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name;

-- Bob shows 0, not 1×NULL

การกรองรายการที่ไม่ตรงกันออก

ข้อควรระวังที่ไม่เด่นชัด: การใส่เงื่อนไขของตารางฝั่งขวาไว้ใน WHERE หลังการใช้ LEFT JOIN จะเปลี่ยนให้เป็นการ JOIN ภายใน เพราะ NULL = value มีสถานะไม่ทราบค่าและจะถูกกรองออก

หากต้องการเก็บแถวที่ไม่ตรงกันไว้ ให้ใส่เงื่อนไขในส่วน ON หรือตรวจสอบ NULL อย่างชัดเจน

-- Accidentally drops Bob (his o.status is NULL)
SELECT c.name FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.status = 'open';

-- Keep unmatched rows: move the test into ON
SELECT c.name FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id AND o.status = 'open';

หลักจำง่าย

นำหลักเหล่านี้ไปใช้กับคำสั่งสืบค้นที่ใช้การรวมและ JOIN ทุกครั้ง:

  • ฟังก์ชันรวมไม่สนใจค่า NULL (ยกเว้น COUNT(*))
  • COUNT(col) < COUNT(*) เมื่อ col มีค่า NULL
  • SUM/AVG ของชุดว่างเป็น NULL — ครอบด้วย COALESCE
  • LEFT JOIN สร้างค่า NULL สำหรับรายการที่ไม่ตรงกัน ให้นับคีย์ฝั่งขวา
  • ตัวกรองของตารางฝั่งขวาควรอยู่ใน ON ไม่ใช่ WHERE
SELECT c.name,
  COALESCE(SUM(o.amount), 0) AS spent,
  COUNT(o.id)                AS orders
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name;

ตรวจสอบความเข้าใจ

คอลัมน์ amount มีค่า 100, NULL และ 200 ในสามแถว COUNT(*) และ COUNT(amount) จะคืนค่าเท่าใด

ทบทวน

คุณได้เรียนรู้ว่า NULL ไหลผ่านการรวมข้อมูลและการ JOIN อย่างไร: ฟังก์ชันรวมข้ามค่า NULL, COUNT(*) นับแถวในขณะที่ COUNT(col) นับค่าที่ไม่ใช่ NULL, ผลรวมของชุดว่างเป็น NULL และ GROUP BY รวมค่า NULL ไว้ในกลุ่มเดียว

คุณยังได้เห็นว่าการ JOIN ภายนอกสร้างค่า NULL สำหรับรายการที่ไม่ตรงกัน และเหตุใดตัวกรองของตารางฝั่งขวาจึงควรอยู่ใน ON บทนี้เป็นการจบหลักสูตรการทำงานกับค่า NULL ตอนนี้คุณสามารถจัดการข้อมูลที่หายไปได้อย่างมั่นใจ

-- A NULL-safe summary query
SELECT c.name,
  COUNT(o.id)                AS orders,
  COALESCE(SUM(o.amount), 0) AS total_spent
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name
ORDER BY total_spent DESC;

คำถามที่พบบ่อย

บทเรียน “NULL ในการรวมค่าและการเชื่อมตาราง” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “NULL ในการรวมค่าและการเชื่อมตาราง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “NULL ในการรวมค่าและการเชื่อมตาราง”

NULL มีพฤติกรรมอย่างไรใน COUNT, SUM และ JOIN คุณปฏิบัติ SQL Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “NULL ในการรวมค่าและการเชื่อมตาราง” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน SQL Academy นี้ได้ไหม

ได้ บทเรียน SQL Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ความหมายที่แท้จริงของ NULL
  2. IS NULL และ IS NOT NULL
  3. COALESCE และ NULLIF
  4. NULL ในการรวมค่าและการเชื่อมตาราง
← กลับไปที่ SQL Academy