SQL Academy · درس

قيم NULL في التجميعات والضم

تعرّف إلى سلوك NULL في COUNT وSUM وJOIN

الدرس 4 من 413 خطوة

قيم NULL في التجميعات والضم درس مجاني في SQL Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في SQL Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة SQL Academy 4 دروس في المجموع.

تغيّر قيم NULL العمليات الحسابية

تتعامل دوال التجميع وعمليات الربط مع NULL بطرق خاصة. وإذا لم تكن تعرف هذه القواعد، فقد تصبح المجاميع وأعداد الصفوف غير صحيحة دون أن تلاحظ ذلك.

يوضح هذا الدرس كيفية تفاعل COUNT وSUM وAVG وGROUP BY وعمليات الربط الخارجي مع القيم المفقودة.

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

تتجاهل دوال التجميع قيم NULL

تتخطى معظم دوال التجميع، مثل SUM وAVG وMIN وMAX، قيم NULL ببساطة. فهي تجمع الصفوف التي تحتوي على بيانات فقط.

لذلك لا تؤدي قيمة amount تساوي 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(column)

يخلط هذا الفرق بين كثير من الأشخاص:

  • تعدّ 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 بالكامل، — فلا تُضيف أبدًا إلى العدد المميز.

ضع ذلك في اعتبارك عند قياس «عدد قيم X الفريدة».

-- 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 الناتجة عن عمليات الربط الخارجي

تُعد عمليات الربط الخارجي مصدرًا رئيسيًا لقيم 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 يحوّله إلى ربط داخلي، لأن 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';

قواعد عامة

طبّق هذه القواعد في كل استعلام يجمع بين التجميع والربط:

  • تتجاهل دوال التجميع قيم 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 عبر عمليات التجميع والربط: تتخطى دوال التجميع قيم NULL، وتعدّ COUNT(*) الصفوف بينما تعدّ COUNT(col) القيم غير NULL، وتكون مجاميع المجموعات الفارغة NULL، ويجمع GROUP BY قيم NULL في مجموعة واحدة.

ورأيت أيضًا أن عمليات الربط الخارجي تُنشئ قيم 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;
البدء مجانًا

تعلم SQL مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
46
الدروس
183

الأسئلة الشائعة

هل درس «قيم NULL في التجميعات والضم» مجاني؟

نعم — نص درس «قيم NULL في التجميعات والضم» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة SQL Academy، انتقل إلى CoddyKit PRO. تتضمن دورة SQL Academy 4 دروس في المجموع.

ماذا ستتعلم في «قيم NULL في التجميعات والضم»؟

تعرّف إلى سلوك NULL في COUNT وSUM وJOIN تتمرن على SQL Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ SQL Academy؟

لا تُشترط خبرة سابقة. SQL Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «قيم NULL في التجميعات والضم»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس SQL Academy هذا؟

نعم. كل درس في SQL Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. ما الذي يعنيه NULL فعليًا
  2. IS NULL وIS NOT NULL
  3. COALESCE وNULLIF
  4. قيم NULL في التجميعات والضم
← العودة إلى SQL Academy