في هذا الدرس 6تصفّح المواضيع
الاستعلام الفرعي هو جملة SELECT محاطة بقوسين ومتداخلة داخل استعلام SQL خارجي. وأبسط أشكاله هو الاستعلام الفرعي مفرد القيمة (Scalar Subquery) الذي يرجع صفاً واحداً وعموداً واحداً كحد أقصى (قيمة مفردة واحدة):
- صالح في موضع أي قيمة: لأنه يُقيّم إلى قيمة وحيدة، يمكنك وضعه يمين معاملات المقارنة القياسية (
=و>و<) داخلWHEREأوHAVINGأو حتى كعمود محسوب فيSELECT. - قيد القيمة الوحيدة: إذا أرجع الاستعلام الفرعي المفرد أكثر من صف واحد أثناء التنفيذ، يوقف MySQL الاستعلام فوراً بالخطأ رقم 1242.
-- Find products priced higher than the overall catalog average
SELECT
product_id,
product_title,
unit_price
FROM products
WHERE unit_price > (
SELECT AVG(unit_price)
FROM products
)
ORDER BY unit_price DESC;
عندما يرجع الاستعلام الداخلي عموداً واحداً يحتوي على عدة صفوف، فإنه يشكّل قائمة قيم. ولا يجوز مقارنة القائمة بمعامل المساواة المجرد =، بل نستخدم معها المعامل IN:
- فحص الانتماء للقائمة: تختبر الصيغة
WHERE user_id IN (SELECT ...)ما إذا كانت قيمة العمود الخارجي مطابقة لأي قيمة ضمن مخرجات الاستعلام الفرعي. - فخ
NOT INمعNULL: إذا احتوت مخرجات الاستعلام الفرعي على قيمةNULLواحدة فقط، فإن الشرطNOT IN (SELECT ...)يُقيّم إلى غير معروفUNKNOWNويرجع صفراً من الصفوف! لذلك أضف دائماًWHERE col IS NOT NULLداخل استعلامNOT IN.
-- Find customers who placed at least one high-value order in 2026
SELECT
user_id,
full_name,
email
FROM users
WHERE user_id IN (
SELECT user_id
FROM orders
WHERE total_amount >= 500.00
AND user_id IS NOT NULL
);
لمقارنة قيمة خارجية بقائمة متعددة الصفوف باستخدام معاملات المتباينات (> و< و>= و<=)، يوفّر MySQL محددات الكمية ANY (أو مرادفه SOME) وALL:
- المقارنة بـ
> ANY (subquery): تتحقق متى كانت القيمة الخارجية أكبر من قيمة واحدة على الأقل داخل قائمة الاستعلام الفرعي (أي أكبر من الحد الأدنى للقائمة). - المقارنة بـ
> ALL (subquery): لا تتحقق إلا إذا كانت القيمة الخارجية أكبر من جميع القيم الموجودة في الاستعلام الفرعي بلا استثناء (أي أكبر من القيمة العظمى للقائمة).
-- Find products more expensive than EVERY product in category 4
SELECT
product_id,
product_title,
category_id,
unit_price
FROM products
WHERE unit_price > ALL (
SELECT unit_price
FROM products
WHERE category_id = 4
);
يرجع الاستعلام الفرعي الصفّي (Row Subquery) صفاً يحتوي على عمودين أو أكثر كحزمة مركبة، مما يتيح مقارنة عدة أعمدة معاً في خطوة واحدة باستخدام منشئ الصف (col1, col2) على الطرف الأيسر:
- المطابقة المركبة: تتحقق العبارة
WHERE (department_id, salary) = (SELECT ...)من تطابق العمودين معاً مع الصف الناتج من الاستعلام الداخلي. - فحص القوائم المركبة بـ
IN: يمكنك أيضاً استخدام منشئ الصف مع المعاملINمثلWHERE (warehouse_id, sku_code) IN (SELECT ...).
-- Match composite (category_id, unit_price) against top item
SELECT product_id, product_title, category_id, unit_price
FROM products
WHERE (category_id, unit_price) = (
SELECT category_id, unit_price
FROM products
ORDER BY unit_price DESC
LIMIT 1
);
عند وضع استعلام فرعي داخل جملة FROM، يعامل MySQL مخرجاته كجدول مؤقت افتراضي يُسمى الجدول المشتق (Derived Table):
- إلزامية الاسم المستعار: يشترط MySQL منح كل جدول مشتق اسماً مستعاراً بعد قوس الإغلاق مباشرةً (مثل
FROM (SELECT ...) AS order_totals)، وإغفاله يطلق الخطأ رقم 1248. - التجميع ثنائي المراحل: تتيح الجداول المشتقة حساب متوسط المجاميع (مثل متوسط إجمالي إنفاق كل عميل) وهو ما لا يمكن كتابته مباشرة بتداخل
AVG(SUM(...)).
-- Compute average customer lifetime spend via a derived table in FROM
SELECT
COUNT(*) AS active_customers,
ROUND(AVG(customer_totals.lifetime_spend), 2) AS avg_lifetime_spend
FROM (
SELECT user_id, SUM(total_amount) AS lifetime_spend
FROM orders
WHERE status = 'paid'
GROUP BY user_id
) AS customer_totals;
يقارن الجدول التالي بين أشكال الاستعلامات الفرعية الأربعة وقواعدها في MySQL 8:
| شكل الاستعلام الفرعي | أبعاد النتيجة المرجعة | المعاملات والمواضع المسموحة | القاعدة الأساسية في MySQL |
|---|---|---|---|
| استعلام مفرد القيمة (Scalar) | صف واحد، عمود واحد | = و> و< في WHERE أو SELECT | يطلق الخطأ 1242 إذا أرجع أكثر من صف واحد |
| استعلام القائمة (Column List) | 0..N صفوف، عمود واحد | IN وNOT IN وANY وALL | استبعد قيم NULL داخل NOT IN لتجنب تصفير النتيجة |
| استعلام الصف المركب (Row) | صف أو أكثر، عمودان فأكثر | (c1, c2) = (...) أو IN (...) | يجب تطابق عدد الأعمدة بين الطرفين |
| الجدول المشتق (Derived Table) | جدول كامل داخل FROM | FROM (SELECT ...) AS alias | يطلق الخطأ 1248 إذا لم تمنحه اسماً مستعاراً |
ملخص الدرس: أتقنّا في هذا الدرس الاستعلامات الفرعية مفردة القيمة، واستعلامات القوائم بمعاملات IN وANY وALL، ومقارنة الصفوف المركبة، واستخدام الجداول المشتقة داخل جملة FROM.
الخطوة التالية والدرس القادم: في الدرس القادم سنتعمق في «الاستعلامات الفرعية المترابطة ومعامل EXISTS في MySQL».
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
تمنحك الاستعلامات الفرعية المفردة والقوائم (IN وANY وALL) والجداول المشتقة قدرة عالية على التصفية والتجميع متعدد المراحل. الخطوة التالية: انتقل إلى درس «الاستعلامات الفرعية المترابطة ومعامل EXISTS في MySQL».
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات5
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 SQL Subqueries الاستعلامات الفرعية
- تعلّم الاستعلامات الفرعية مع IN و ANY و ALL والجداول المشتقة في MySQL بأسلوب MySQL 8 الحديث مع أمثلة استعلامات SQL وتطبيقات تفاعلية.
- للمراجعة
- 02 Scalar Single Value Subqueries الاستعلام الفرعي مفرد القيمة
- المفهوم الهندسي والصياغة العملية الخاصة بقسم الاستعلام الفرعي مفرد القيمة في MySQL 8.
- للمراجعة
- 03 List Subqueries with IN Operator استعلامات القوائم بمعامل IN
- المفهوم الهندسي والصياغة العملية الخاصة بقسم استعلامات القوائم بمعامل IN في MySQL 8.
- للمراجعة
- 04 Comparing Against ANY and ALL المقارنة بمعاملي ANY و ALL
- المفهوم الهندسي والصياغة العملية الخاصة بقسم المقارنة بمعاملي ANY و ALL في MySQL 8.
- للمراجعة
- 05 Row Subqueries Tuple Comparisons مقارنة الصفوف بالاستعلام الفرعي
- المفهوم الهندسي والصياغة العملية الخاصة بقسم مقارنة الصفوف بالاستعلام الفرعي في MySQL 8.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات3
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Scalar قيمة مفردة
- Scalar Subquery (1x1 Result)
- استعلام فرعي يرجع صفاً واحداً وعموداً واحداً كحد أقصى ويُعامل كقيمة وحيدة.
- للمراجعة
- 02 Derived Table جدول مشتق
- Inline FROM-Clause Subquery
- استعلام فرعي يوضع داخل جملة FROM مع اسم مستعار إلزامي ليُعامل كجدول مؤقت.
- للمراجعة
- 03 Semi-Join شبه ربط
- Optimizer Semi-Join Transformation
- استراتيجية في محسّن MySQL 8 لتنفيذ استعلامات IN بكفاءة دون تكرار صفوف الجدول الخارجي.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
نفّذ أمثلة SQL المشروحة في قسم الاستعلام الفرعي مفرد القيمة داخل قاعدة بياناتك المحلية وتحقق من مجموعة النتائج.
-
بدّل بين الحالات التفاعلية في قسم استعلامات القوائم بمعامل IN وقارن كيف ينفّذ محرك MySQL 8 كل استعلام.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي5 أسئلة تنتظرك +
ماذا يحدث في MySQL إذا أرجع استعلام فرعي مفرد مستخدم مع WHERE price = (SELECT ...) ثلاثة صفوف بدلاً من صف واحد؟
تذكّر قاعدة عدد الصفوف المسموح به مع معامل المساواة المفرد.
لماذا يرجع الشرط WHERE category_id NOT IN (SELECT ...) صفراً من الصفوف إذا احتوت مخرجات الاستعلام الفرعي على قيمة NULL واحدة؟
فكّر في نتيجة المقارنة المنطقية x <> NULL في SQL.
أي محدد كمية يجعل الشرط WHERE unit_price > ... (SELECT ...) محققاً فقط عندما يتجاوز السعر أعلى سعر موجود في الفئة 2 بالكامل؟
قارن بين دلالة ANY ودلالة ALL مع معامل أكبر من.
في MySQL، يتيح منشئ الصف مثل WHERE (dept_id, role_id) = (SELECT ...) مقارنة العمودين معاً في نفس الوقت مقابل صف مركب ناتج عن استعلام فرعي.
تحقق من دعم MySQL لمقارنة الصفوف المركبة في الاستعلامات الفرعية.
ما هي القاعدة النحوية الإلزامية عند وضع استعلام فرعي داخل جملة FROM (جدول مشتق) في MySQL؟
تذكّر السبب الذي يطلق الخطأ رقم 1248 في الجداول المشتقة.