ضمِّن استعلامًا داخل آخر للمقارنة مع قيمة مجمّعة، أو التصفية بناءً على مجموعة، أو اختبار الوجود.
افتح هذا الدرس في Kodokonإن الاستعلام الفرعي استعلام موضوع بين قوسين داخل استعلام آخر. وفي تعليمة واحدة، يجيب عن أسئلة مثل "الطلبات التي تفوق المتوسط" أو "العملاء الذين لديهم طلب واحد على الأقل". شغّل هذا السكربت في sqliteonline.com أو sqlite3 قبل أن تبدأ.
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
amount REAL NOT NULL
);
INSERT INTO customers (id, name) VALUES
(1, 'Alice'), (2, 'Karim'),
(3, 'Mina'), (4, 'Paulo');
INSERT INTO orders (id, customer_id, amount)
VALUES
(1, 1, 49.90), (2, 1, 15.00),
(3, 2, 120.50), (4, 2, 80.00),
(5, 3, 9.90), (6, 1, 200.00);عند وضعه في WHERE، يجب أن يُرجِع الاستعلام الفرعي العددي (scalar) قيمة واحدة: صف واحد، عمود واحد. يحسبه المحرك أولًا، ثم يستخدمه مثل أيّ ثابت آخر. ولا يمكنك فعل ذلك باستخدام WHERE amount > AVG(amount) بسيطة، فهي ممنوعة في SQL.
SELECT id, customer_id, amount
FROM orders
WHERE amount > (
SELECT AVG(amount) FROM orders
);يقارن IN عمودًا مع مجموعة القيم التي يُرجِعها الاستعلام الفرعي. ويختبر EXISTS ما إذا كان الاستعلام الفرعي المرتبط (correlated) (فهو يشير إلى c.id، وهو عمود من الاستعلام الخارجي) يُرجِع صفًا واحدًا على الأقل: يتوقف المحرك حالما يُعثر على أول تطابق.
SELECT name FROM customers
WHERE id IN (
SELECT customer_id FROM orders
WHERE amount > 100
);
SELECT c.name FROM customers AS c
WHERE EXISTS (
SELECT 1 FROM orders AS o
WHERE o.customer_id = c.id
);في FROM، يتصرف الاستعلام الفرعي مثل جدول مؤقت، يُسمى الجدول المشتق (derived table)، ويجب أن يُمنح اسمًا مستعارًا. إنه الأداة الكلاسيكية للتجميع على خطوتين: أولًا إجمالي لكل عميل، ثم متوسط تلك الإجماليات.
SELECT ROUND(AVG(t.total), 2) AS avg_basket
FROM (
SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id
) AS t;