الاستعلامات الفرعية Subqueries في SQL

من موسوعة حسوب
< SQL
مراجعة 15:38، 28 يناير 2018 بواسطة عبد اللطيف ايمش (نقاش | مساهمات) (استبدال النص - '\[\[تصنيف:(.*)\]\]' ب'{{SUBPAGENAME}}')

الاستعلام الفرعي هو استعلام واقعٌ ضمن استعلام آخر بهدف استخدام البيانات الناتجة عنه في الاستعلام الرئيسي الذي يحتويه، وغالبًا ما يكون الاستعلام الفرعي عبارة عن استعلام SELECT، ويمكن استخدامه مع أي من استعلامات SELECT أو INSERT أو UPDATE أو DELETE.

استخدام الاستعلام الفرعي في استعلام SELECT

تحديد الاستعلام الفرعي كأحد الأعمدة

يُمكن تحديد أحد الأعمدة التي ستظهر بتنفيذ استعلام SELECT من خلال الاستعلام الفرعي الذي يعيد قيمة وحيدة لكل سجل.

مثال

إن كانت الجداول الآتية موجودة في قاعدة البيانات:

الجدول الأول: السيارات cars

Colour Price Year Company Model CarID
White 22,500 2018 KIA Optima 05081
Red 25,995 2017 KIA Optima Hybrid 05082
Red 31,900 2018 KIA Stinger 05083
Black 31,990 2017 KIA Cadenza 05084
Blue 23,240 2018 KIA Niro 05085
Grey 14,200 2018 KIA Rio 5-Door 05086
Blue 18,200 2018 KIA Forte5 05087
Blue 32,250 2017 KIA Soul EV 05088
Red 23,385 2017 Nissan Altima 05089
White 46,195 2017 Nissan Armada 05090
Black 33,495 2017 Nissan Maxima 05091
Black 30,715 2017 Nissan Murano 05092
Grey 31,265 2017 Nissan Pathfinder 05093
White 17,875 2017 Nissan Sentra 05094
Red 12,875 2017 Nissan Versa 05095

الجدول الثاني: الزبائن customers

Remaining CarID Name CustomerID
15,495 05091 Mona Sinno 0156
8,875 05095 Ahmad Najjar 0157
19,500 05081 Kareem al-Hamdan 0158
11,875 05094 Mohammad Qadi 0159
17,500 05081 Rasha Mostafa 0160
10,200 05087 Jaber Hammad 0161
19,990 05084 Wessam Fattah 0162
8,875 05094 Shadi Sharif 0163
12,500 05081 Iman Mansour 0164
6,875 05095 Monther Zein 0165
9,200 05087 Rami Fares 0166
18,240 05085 Ammar Arab 0167

إن تنفيذ الاستعلام الآتي:

SELECT CarID, Model, Company, 
  ( SELECT count(*) 
    FROM customers
    WHERE customers.CarID = cars.CarID
  ) AS NumberOrders
FROM cars;

سيعرض عدد المشترين لكل سيارة من السيارات بعمودٍ منفصلٍ (NumberOrders) اعتمادًا على الاستعلام الفرعي المُنفَّذ في الجدول customers بحيث يكون الرقم التسلسلي لطلب السيارة في جدول الزبائن مساويًا للرقم التسلسلي للسيارة في جدول السيارات، وستظهر النتائج:

NumberOrders Company Model CarID
3 KIA Optima 05081
0 KIA Optima Hybrid 05082
0 KIA Stinger 05083
1 KIA Cadenza 05084
1 KIA Niro 05085
0 KIA Rio 5-Door 05086
2 KIA Forte5 05087
0 KIA Soul EV 05088
0 Nissan Altima 05089
0 Nissan Armada 05090
1 Nissan Maxima 05091
0 Nissan Murano 05092
0 Nissan Pathfinder 05093
2 Nissan Sentra 05094
2 Nissan Versa 05095

تحديد الاستعلام الفرعي كجدول جزئي من جدول أساسي

يمكن استخدام الاستعلام الفرعي للحصول على جدول جزئي مقتبس من جدول أساسي لاستخدامه في عبارة FROM، كما في الاستعلام الآتي:

SELECT cars.CarID, cars.Model, result.CustomerID
FROM  cars JOIN 
  (SELECT * FROM customers 
   WHERE CustomerID BETWEEN 0160 AND 0165
  ) AS result
ON cars.CarID = result.CarID;

إن تنفيذ هذا الاستعلام على الجدولين cars و customers في قاعدة البيانات سيؤدي إلى عرض الرقم التسلسلي ونوع السيارة من الجدول الناتج عن الربط ما بين جدول cars وجدول فرعي يُؤخذ من جدول customers بحيث يكون الرقم التسلسلي للزبون واقعًا ما بين الرقمين 0160 و 0165 وتسميته باسم result إذ يتم الربط عندما يكون الرقم التسلسلي في الجدولين متساويًا، وتكون نتيجة تنفيذه:

CustomerID Model CarID
0160 Optima 05081
0164 Optima 05081
0162 Cadenza 05084
0161 Forte5 05087
0163 Sentra 05094
0165 Versa 05095

استخدام الاستعلام الفرعي لتحديد قيم ضمن الشرط WHERE

تمكن الاستفادة من الاستعلام الفرعي لتحديد عدد من القيم لتوضع ضمن الشرط في عبارة WHERE.

لمعرفة السيارات التي لم تُشترَ من قبل أيّ من الزبائن يمكن استخدام الاستعلام الآتي:

SELECT * 
FROM cars
WHERE CarID NOT IN(
  SELECT CarID
  FROM customers
   );

لتظهر النتائج:

Colour Price Year Company Model CarID
Red 25,995 2017 KIA Optima Hybrid 05082
Red 31,900 2018 KIA Stinger 05083
Grey 14,200 2018 KIA Rio 5-Door 05086
Blue 32,250 2017 KIA Soul EV 05088
Red 23,385 2017 Nissan Altima 05089
White 46,195 2017 Nissan Armada 05090
Black 30,715 2017 Nissan Murano 05092
Grey 31,265 2017 Nissan Pathfinder 05093

ولمعرفة مجموع أسعار السيارات التي لم تُشترى يمكن إضافة الدالة التجميعيّة sum للاستعلام السابق ليصبح:

SELECT Price(*) AS Total 
FROM cars
WHERE CarID NOT IN(
  SELECT CarID
  FROM customers
  );

وتظهر النتيجة:

Total
235,905

حذف السجلات التي تحقق شرط محدد باستعلام فرعي

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

فلحذف السيارات التي اشتراها أيّ من الزبائن في جدول customers من الجدول cars، يصبح الاستعلام بالشكل الآتي:

DELETE FROM cars
WHERE CarID IN(
  SELECT CarID
  FROM customers
  );

ليصبح الجدول cars في قاعدة البيانات على النحو الآتي:

Colour Price Year Company Model CarID
Red 25,995 2017 KIA Optima Hybrid 05082
Red 31,900 2018 KIA Stinger 05083
Grey 14,200 2018 KIA Rio 5-Door 05086
Blue 32,250 2017 KIA Soul EV 05088
Red 23,385 2017 Nissan Altima 05089
White 46,195 2017 Nissan Armada 05090
Black 30,715 2017 Nissan Murano 05092
Grey 31,265 2017 Nissan Pathfinder 05093

تحديث قيم السجلات اعتمادًا على الاستعلام الفرعي

يمكن الاعتماد على الاستعلام الفرعي لتحديد القيم الجديدة التي ستوضع في الحقل المطلوب في استعلام UPDATE، إن كان جدول الأقساط installments الآتي موجودًا في قاعدة البيانات:

Date CustomerID Amount TransactionID
04/11/2017 0156 7,000 0206
11/11/2017 0157 5,000 0207
01/11/2017 0158 9,000 0208
09/11/2017 0159 6,000 0209
24/11/2017 0160 8,000 0210
11/11/2017 0161 7,000 0211
04/11/2017 0162 9,000 0212
09/11/2017 0163 5,000 0213
01/11/2017 0164 8,000 0214
09/11/2017 0165 4,000 0215
04/11/2017 0166 5,000 0216
01/11/2017 0167 10,000 0217

فلتحديث قيمة المبلغ المتبقي في جدول الزبائن customers بحسب القيمة المدفوعة في الجدول السابق يُنفذ الاستعلام الآتي:

UPDATE customers 
SET remaining = remaining - 
  (SELECT Amount
   FROM installments
   WHERE customers.CustomerID = installments.CustomerID);

ليصبح الجدول كما يلي:

Remaining CarID Name CustomerID
8,495 05091 Mona Sinno 0156
3,875 05095 Ahmad Najjar 0157
10,500 05081 Kareem al-Hamdan 0158
5,875 05094 Mohammad Qadi 0159
9,500 05081 Rasha Mostafa 0160
3,200 05087 Jaber Hammad 0161
10,990 05084 Wessam Fattah 0162
3,875 05094 Shadi Sharif 0163
4,500 05081 Iman Mansour 0164
2,875 05095 Monther Zein 0165
4,200 05087 Rami Fares 0166
8,240 05085 Ammar Arab 0167

إضافة سجلات في جدول من جدول آخر باستخدام الاستعلام الفرعي

تمكن إضافة بعض السجلات إلى الجدول من جدول آخر اعتمادًا على استعلام فرعي بحيث تتوافق أسماء الأعمدة المختارة ما بين الجدولين.

ليكن الجدول الآتي cheapCars موجودًا في قاعدة البيانات:

Colour Price Year Company Model CarID
Grey 12,800 2014 Nissan Versa 1.6 S 06002
WHITE 14,700 2014 KIA Rio LX 06003
Blue 13,790 2014 Mitsubishi Mirage DE 06004

لإضافة سيارات أخرى لهذا الجدول من الجدول الأساسي cars يُمكن الاعتماد على الاستعلام الفرعي بالشكل الآتي:

INSERT INTO cheapCars 
SELECT * FROM cars WHERE Price < 20000;

ليصبح الجدول:

Colour Price Year Company Model CarID
Grey 12,800 2014 Nissan Versa 1.6 S 06002
WHITE 14,700 2014 KIA Rio LX 06003
Blue 13,790 2014 Mitsubishi Mirage DE 06004
Grey 14,200 2018 KIA Rio 5-Door 05086
Blue 18,200 2018 KIA Forte5 05087
White 17,875 2017 Nissan Sentra 05094
Red 12,875 2017 Nissan Versa 05095

التوافقية

SQLServer SQLite Oracle PostgreSQL MySQL
نعم نعم نعم نعم نعم

مصادر