التجميعات دون GROUP BY
كيفية اختزال تجميع مجرد لجدول كامل في صف واحد
التجميعات دون GROUP BY درس مجاني في SQL Interview Prep على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في SQL Interview Prep، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة SQL Interview Prep 4 دروس في المجموع.
دالة تجميعية واحدة، صف واحد
يختبر المحاورون فكرة أساسية بهذا السؤال: «ماذا يحدث عند استخدام دالة تجميعية من دون GROUP BY؟»
الإجابة: ينهار الجدول بأكمله إلى صف واحد. تتعامل الدالة التجميعية مع جميع الصفوف المؤهلة باعتبارها مجموعة ضمنية كبيرة واحدة. ويساعد فهم نموذج «المجموعة الضمنية» هذا على تفسير العديد من القواعد اللاحقة، لذلك دعونا نبنيه بعناية.
المجموعة الواحدة الضمنية
عند كتابة دالة تجميعية مستقلة من دون GROUP BY، تتصرف SQL كما لو كانت هناك مجموعة واحدة تحتوي على كل صف. وتكون النتيجة دائمًا صفًا واحدًا بالضبط، مهما كان عدد صفوف الجدول — حتى لو كان الجدول فارغًا.
لذلك يُرجع SELECT COUNT(*) FROM employees صفًا واحدًا يحتوي على رقم واحد يلخص الجدول بأكمله.
SELECT COUNT(*) AS total_employees
FROM employees;
-- always returns exactly one rowعدة دوال تجميعية معًا
يمكنكم إدراج عدة دوال تجميعية في SELECT واحد. فجميعها تلخص المجموعة الضمنية نفسها، ولذلك تحصلون على صف واحد بالضبط يحتوي على عدة أعمدة.
هذا هو الاستعلام المعتاد من نوع «أعطني إحصاءات الملخص». فالأرقام الأربعة جميعها تصف مجموعة الصفوف الكاملة نفسها.
SELECT
COUNT(*) AS num_rows,
SUM(salary) AS total_pay,
AVG(salary) AS avg_pay,
MAX(salary) AS top_pay
FROM employees;خطأ المزج
إليكم القاعدة الأكثر ورودًا في الاختبارات. لا يمكنكم مزج دالة تجميعية مستقلة مع عمود غير تجميعي في SELECT نفسه من دون GROUP BY.
لماذا؟ تُنتج الدالة التجميعية صفًا واحدًا، بينما يحتوي العمود العادي على قيم متعددة — فأي قيمة سيعرضها؟ الأمر ملتبس، ولذلك تُصدر SQL القياسية خطأ.
-- ERROR: name is not aggregated and there is no GROUP BY
SELECT name, MAX(salary)
FROM employees;سبب الالتباس
فكّروا في الأمر باستخدام جدولنا. تختزل MAX(salary) جميع الصفوف إلى قيمة واحدة. لكن يحتوي name على قيمة مختلفة في كل صف. ولا يمكن لصف الملخص الواحد أن يحتوي على خمسة أسماء في خلية واحدة.
ترفض قاعدة البيانات التخمين. وهذا هو المبدأ نفسه الذي تقوم عليه قاعدة GROUP BY: يجب أن يكون كل عمود محدد إما مجمعًا أو جزءًا من المجموعة. وعند عدم وجود GROUP BY، لا يُسمح إلا بالدوال التجميعية.
استثناء MySQL المتساهل
هناك تفصيل جدير بالذكر يتعلق بإحدى اللهجات: كانت MySQL القديمة أو غير الصارمة تسمح باستعلام المزج، وتُرجع اسمًا عشوائيًا — وليس بالضرورة اسم صاحب أعلى راتب.
أما MySQL الحديثة مع تفعيل ONLY_FULL_GROUP_BY (وهو الإعداد الافتراضي الآن)، فترفض هذا الاستعلام مثل بقية الأنظمة. وذكر ذلك يُظهر وعيًا بالاختلافات بين اللهجات، لكن تعاملوا دائمًا مع استعلام المزج على أنه غير صحيح.
جلب الصف المرتبط بالقيمة القصوى
إذًا، كيف تحصلون على اسم الموظف الأعلى أجرًا؟ ليس عن طريق المزج. استخدموا ORDER BY + LIMIT، أو استعلامًا فرعيًا يقارن بالقيمة التجميعية.
نسخة ORDER BY/LIMIT هي الأبسط. أما نسخة الاستعلام الفرعي فتتعمم بصورة جيدة، وتُرجع جميع الموظفين المتعادلين في أعلى قيمة.
-- Subquery: returns everyone earning the max
SELECT name, salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);الدوال التجميعية على جدول فارغ
حالة طرفية قد يطرحها المحاورون: «ماذا تُرجع الدالة التجميعية المستقلة على جدول فارغ؟»
- تُرجع
COUNT(*)القيمة 0 (صفًا واحدًا، وقيمته 0). - تُرجع
SUMوAVGوMINوMAXالقيمة NULL (صفًا واحدًا، وقيمته NULL).
والأهم أنكم تحصلون دائمًا على صف واحد، وليس صفر صفوف أبدًا. فهذا الضمان بوجود صف واحد هو جوهر الدالة التجميعية من دون GROUP BY.
SELECT COUNT(*) AS c, SUM(salary) AS s, MAX(salary) AS m
FROM employees
WHERE 1 = 0;
-- one row: c=0, s=NULL, m=NULLلا يمكن وضع دالة تجميعية داخل WHERE
قاعدة أخرى تنتج عن هذا النموذج: لا يمكنكم وضع دالة تجميعية في جملة WHERE، لأن WHERE ترشح الصفوف الفردية قبل حدوث التجميع.
ولترشيح نتيجة دالة تجميعية، استخدموا HAVING (مع التجميع)، أو ضعوا الدالة التجميعية داخل استعلام فرعي. فـ WHERE تُنفَّذ مبكرًا جدًا في ترتيب التنفيذ بحيث لا يمكنها رؤية النتيجة التجميعية.
-- ERROR: aggregate not allowed in WHERE
-- SELECT * FROM employees WHERE salary > AVG(salary);
-- Correct: compare to the aggregate via subquery
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);الدالة التجميعية المستقلة مقابل GROUP BY
صيغوا الفرق لأنفسكم كما يلي:
- من دون GROUP BY: مجموعة ضمنية واحدة = الجدول بأكمله = صف نتيجة واحد بالضبط.
- مع GROUP BY col: مجموعة واحدة لكل قيمة مميزة في col = صف واحد لكل مجموعة.
الدالة التجميعية المستقلة هي ببساطة GROUP BY من دون أعمدة تجميع. الآلية نفسها، لكن في حاوية كبيرة واحدة.
-- Whole table: one row
SELECT AVG(salary) FROM employees;
-- Per department: one row each
SELECT department, AVG(salary)
FROM employees
GROUP BY department;كيفية شرح ذلك
إجابة واضحة: «تتعامل الدالة التجميعية من دون GROUP BY مع مجموعة النتائج بأكملها باعتبارها مجموعة ضمنية واحدة، وتُرجع صف ملخص واحدًا بالضبط، حتى مع وجود جدول فارغ. ولا يمكن تحديد عمود غير تجميعي إلى جانبها، لأن قيمة ذلك العمود ستكون ملتبسة. ولجلب الصف المرتبط بـ MAX أو MIN، أستخدم ORDER BY مع LIMIT أو استعلامًا فرعيًا يقارن بالقيمة التجميعية».
تحقق سريع
توقّعوا شكل الناتج.
مراجعة
خلاصة الدوال التجميعية من دون GROUP BY:
- يصبح الجدول بأكمله مجموعة ضمنية واحدة → صف نتيجة واحد بالضبط.
- لا يمكنكم مزج دالة تجميعية مستقلة مع عمود غير تجميعي.
- الجدول الفارغ:
COUNT(*)= 0، بينما تُرجع الدوال الأخرى NULL، مع بقاء صف واحد. - لا يمكن أن تظهر الدوال التجميعية في
WHERE؛ استخدموا استعلامًا فرعيًا أوHAVING. - لجلب الصف المرتبط بـ MIN/MAX، استخدموا ORDER BY + LIMIT أو استعلامًا فرعيًا.
بهذا تكتمل تدريبات مقابلات الدوال التجميعية.
الأسئلة الشائعة
هل درس «التجميعات دون GROUP BY» مجاني؟
نعم — نص درس «التجميعات دون GROUP BY» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة SQL Interview Prep، انتقل إلى CoddyKit PRO. تتضمن دورة SQL Interview Prep 4 دروس في المجموع.
ماذا ستتعلم في «التجميعات دون GROUP BY»؟
كيفية اختزال تجميع مجرد لجدول كامل في صف واحد تتمرن على SQL Interview Prep مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ SQL Interview Prep؟
لا تُشترط خبرة سابقة. SQL Interview Prep على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «التجميعات دون GROUP BY»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس SQL Interview Prep هذا؟
نعم. كل درس في SQL Interview Prep يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- COUNT(*) مقابل COUNT(column) مقابل COUNT(DISTINCT)
- SUM وAVG مع NULL
- MIN وMAX والتجميع غير الرقمي
- التجميعات دون GROUP BY