0Pricing
Coding Interview Prep · درس

HAVING مقابل WHERE

التصفية قبل التجميع أو بعده، وأي عبارة ترى التجميع

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

السؤال الذي سيُطرح عليك

يُعد السؤال «ما الفرق بين WHERE وHAVING؟» واحدًا من أكثر أسئلة مقابلات SQL شيوعًا. تقول الإجابة الضعيفة: «تُستخدم HAVING مع القيم التجميعية». أما الإجابة القوية فتشرح متى تُنفَّذ كل عبارة في مسار الاستعلام.

وهذا التوقيت هو جوهر المسألة كلها: تعمل WHERE على تصفية الصفوف قبل التجميع، بينما تعمل HAVING على تصفية المجموعات بعد التجميع.

موضعهما في ترتيب التنفيذ

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

  • FROM / JOIN → بناء مجموعة الصفوف
  • WHERE → تصفية الصفوف الفردية
  • GROUP BY → اختزال الصفوف إلى مجموعات
  • HAVING → تصفية المجموعات
  • SELECT → إسقاط الأعمدة
  • ORDER BY → الفرز

تُنفَّذ WHERE قبل وجود المجموعات، بينما تُنفَّذ HAVING بعد ذلك؛ لذلك يمكن لـ HAVING رؤية القيم التجميعية، ولا يمكن لـ WHERE ذلك.

لا يمكن لـ WHERE رؤية القيم التجميعية

لأن WHERE تُنفَّذ قبل التجميع، فلا تكون لديها أي قيم تجميعية بعد. إن كتابة WHERE COUNT(*) > 5 تؤدي إلى خطأ في الصياغة في كل قاعدة بيانات تلتزم بالمعيار.

يضع المحاورون هذا السطر تحديدًا لاختبار مدى فهمك لمسار التنفيذ. فالدالة التجميعية لا تكون موجودة عند تقييم WHERE.

-- ERROR: aggregate not allowed in WHERE
SELECT department, COUNT(*)
FROM employees
WHERE COUNT(*) > 5
GROUP BY department;

تُصفّي HAVING المجموعات

انقل شرط القيمة التجميعية إلى HAVING، وسيعمل ذلك لأن HAVING تُنفَّذ بعد حساب المجموعات والقيم التجميعية الخاصة بها.

اقرأها هكذا: «جمّع الموظفين، ثم أبقِ الأقسام التي يتجاوز عدد موظفيها خمسة».

SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;

ضع مرشحات الصفوف في WHERE

الخطأ العكسي هو تصفية الصفوف الخام باستخدام HAVING. وغالبًا ما يعطي ذلك الإجابة الصحيحة، لكنه أبطأ ومضلل، لأنك جمّعت صفوفًا كنت تنوي استبعادها.

قاعدة عامة: التصفية بناءً على قيمة عمود خام → WHERE. والتصفية بناءً على قيمة تجميعية → HAVING. تؤدي تصفية الصفوف مبكرًا إلى تقليص البيانات التي يجب على التجميع معالجتها.

-- Better: drop inactive rows BEFORE grouping
SELECT department, COUNT(*) AS headcount
FROM employees
WHERE status = 'active'
GROUP BY department
HAVING COUNT(*) > 5;

استخدام العبارتين معًا

غالبًا ما يستخدم الاستعلام الكامل العبارتين معًا. تعمل WHERE على تضييق نطاق الصفوف أولًا، ثم تُبقي HAVING على المجموعات المطابقة. وتتوافق القراءة من الأعلى إلى الأسفل مع الترتيب المنطقي.

مثال تطبيقي: من بين الطلبات التي أُجريت هذا العام، أوجد العملاء الذين أنفقوا أكثر من 1000 إجمالًا.

SELECT customer_id, SUM(amount) AS total_spent
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY customer_id
HAVING SUM(amount) > 1000;

استخدام HAVING مع أعمدة غير تجميعية

يمكن لـ HAVING الرجوع إلى عمود تجميع، وليس إلى القيم التجميعية فقط. إن HAVING department = 'Sales' صياغة قانونية، لكنها بلا فائدة: يجب وضع هذا المرشح في WHERE لكي يُنفَّذ مبكرًا.

إذا عرض عليك المحاور HAVING تصفّي عمودًا عاديًا مستخدمًا في التجميع، فالنقد المتوقع هو: «انقلها إلى WHERE لتحسين الكفاءة».

-- Works but inefficient; prefer WHERE department = 'Sales'
SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING department = 'Sales';

استخدام HAVING دون GROUP BY

إليك حالة دقيقة: تكون HAVING قانونية حتى من دون GROUP BY. إذ يتحول الجدول بأكمله إلى مجموعة ضمنية واحدة، وتقوم HAVING بتصفية هذه المجموعة.

إذا كان الشرط التجميعي خاطئًا، فستحصل على صفر من الصفوف؛ وإذا كان صحيحًا، فستحصل على صف واحد. هذه الحالة نادرًا ما تكون مفيدة، لكن المحاورين يسألون عنها للتأكد من فهمك لمفهوم المجموعة الضمنية.

-- Returns the count only if the table has > 100 rows
SELECT COUNT(*) AS total
FROM orders
HAVING COUNT(*) > 100;

هل يمكن لـ HAVING استخدام اسم مستعار من SELECT؟

كما هي الحال مع حيلة نطاق الأسماء المستعارة في مواضع أخرى، تختلف اللهجات. تسمح Postgres وMySQL لـ HAVING بالرجوع إلى اسم مستعار من SELECT، بينما لا تسمح بذلك SQL Server وOracle.

والعادة القابلة للنقل بين الأنظمة هي تكرار تعبير الدالة التجميعية في HAVING. فهذا يعمل في كل محرك، ويتجنب المفاجآت في مقابلة تتناول قواعد بيانات متعددة.

-- Portable: repeat the aggregate, do not rely on the alias
SELECT region, SUM(amount) AS total
FROM sales
GROUP BY region
HAVING SUM(amount) > 5000;

منظور الأداء

لإثارة إعجاب المحاور، اربط العبارتين بالأداء: تقلل WHERE عدد الصفوف التي يجب على محرك التجميع فحصها، ويمكنها الاستفادة من الفهارس؛ أما HAVING فتُنفَّذ على مجموعات جُمّعت بالفعل، ولذلك لا يمكنها تقليل تكلفة التجميع.

والخلاصة التي يريد المحاورون سماعها هي: ادفع كل مرشح إلى أبكر موضع ممكن. وحدها الشروط التي تعتمد فعليًا على قيمة تجميعية تحتاج إلى HAVING.

الإجابة في جملة واحدة

احفظ هذه الإجابة للمقابلة: «تُصفّي WHERE الصفوف قبل التجميع ولا يمكنها رؤية القيم التجميعية؛ بينما تُصفّي HAVING المجموعات بعد التجميع، وهي العبارة الوحيدة التي يمكنها اختبار قيمة تجميعية».

أتبعها بقائمة ترتيب التنفيذ، وستكون قد قدمت إجابة كاملة تبدو بمستوى مطور خبير.

تحقق سريع

حدّد العبارة التي ينتمي إليها كل شرط.

خلاصة

WHERE: تصفّي الصفوف قبل GROUP BY، ولا يُسمح فيها بالقيم التجميعية. HAVING: تصفّي المجموعات بعد التجميع، وهي الموضع الوحيد الذي يُسمح فيه بشرط تجميعي.

  • ضع المرشحات المعتمدة على الأعمدة الخام في WHERE لتحسين السرعة والاستفادة من الفهارس.
  • يمكن لـ HAVING الرجوع إلى أعمدة التجميع، لكن لا ينبغي استخدامها للمرشحات العادية.
  • تعمل HAVING من دون GROUP BY على المجموعة الضمنية للجدول بأكمله.
  • كرّر تعبيرات القيم التجميعية في HAVING لضمان التوافق بين اللهجات.

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

هل درس «HAVING مقابل WHERE» مجاني؟

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

ماذا ستتعلم في «HAVING مقابل WHERE»؟

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

هل أحتاج إلى خبرة سابقة لأبدأ Coding Interview Prep؟

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

كم من الوقت يستغرق درس «HAVING مقابل WHERE»؟

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

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

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

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

  1. قاعدة GROUP BY لأعمدة SELECT
  2. HAVING مقابل WHERE
  3. التجميع حسب عدة أعمدة وتعبيرات
  4. عد المجموعات وتصفيتها
← العودة إلى Coding Interview Prep