جب بھی آپ ایس کیو ایل میں کسی دوسرے سوال کے اندر اندر اندر کوئی سوال دیکھتے ہیں، تو یہ ایک ذیلی سوال ہے۔ ذیلی استفسار کو اندرونی سوال بھی کہا جاتا ہے، اور ذیلی استفسار پر مشتمل استفسار کو مین سوال یا بیرونی سوال کہا جاتا ہے۔
ذیلی استفسارات کو ماخوذ کالموں یا اخذ کردہ جدولوں کی شکل میں اضافی ڈیٹا فراہم کرنے کے لیے استعمال کیا جا سکتا ہے، یا مرکزی استفسار کے ذریعے واپس آنے والی قطاروں کو فلٹر کرنے کے لیے۔
ذیلی استفسارات کو سمجھنا بہت مشکل ہو سکتا ہے، خاص طور پر ان ابتدائیوں کے لیے جو صرف SQL کے ساتھ شروعات کر رہے ہیں۔ یہ مضمون اس تصور کو آسان بنانے اور اسے سمجھنے میں بہت آسان بنانے میں مدد کرے گا۔ یہ بالآخر مسائل کو حل کرنے کے لیے ذیلی سوالات کا استعمال آسان بناتا ہے۔
انڈیکس
شرائط:
ذیلی سوالات ایک اعلی درجے کا SQL تصور ہے، اس لیے SQL کی بنیادی باتوں کی ٹھوس سمجھ حاصل کرنا ضروری ہے: SELECT، FROM، WHERE، JOINS، اور CASE اسٹیٹمنٹس اور استفسار پر عمل درآمد کی مناسب ترتیب۔
ذیلی سوالات کیسے کام کرتے ہیں۔
آئیے ذیلی سوال کے ساتھ استفسار کی ایک مثال کو دیکھ کر شروع کریں۔
SELECT *
FROM registration
WHERE student_id
IN (SELECT
id
FROM student
WHERE location = 'Lagos')
مندرجہ بالا استفسار دو حصوں پر مشتمل ہے: مین استفسار اور ذیلی استفسار۔
اہم سوال یہ ہے:
SELECT *
FROM registration
WHERE student_id
IN (...)
فی الحال مین استفسار میں قوسین کے اندر کچھ بھی نہیں ہے۔
مربع بریکٹ میں بند استفسار کا حصہ ایک ذیلی سوال ہے۔ مرکزی استفسار کے ذریعے واپس آنے والی قطاروں کو فلٹر کرنے کے لیے استعمال کیا جاتا ہے۔ اب ذیلی کوڈ کو دیکھتے ہیں۔
SELECT
id
FROM student
WHERE location = 'Lagos'
پھانسی کا حکم
اگر آپ پوری استفسار کو مینجمنٹ سسٹم پر اس طرح چلاتے ہیں:
SELECT *
FROM registration
WHERE student_id
IN (SELECT
id
FROM student
WHERE location = 'Lagos')
آپ کو ذیل میں نتیجہ ملے گا:
نتائج لاگوس کے تمام طلباء کی رجسٹریشن کی تفصیلات دکھاتے ہیں۔ تاہم، اس نتیجہ کو حاصل کرنے کے لیے، ایس کیو ایل ذیل میں بیان کردہ ایک عملدرآمد آرڈر کی پیروی کرتا ہے۔
جب آپ مکمل استفسار چلاتے ہیں تو سب سے پہلے پس منظر میں ذیلی سوالات کا جائزہ لیا جاتا ہے۔
SELECT
id
FROM student
WHERE location = 'Lagos'
ذیلی استفسار طلباء کی میز سے لاگوس کے ایک طالب علم کی ID بازیافت کرتا ہے۔ آپ کو درج ذیل نتیجہ ملتا ہے:

پردے کے پیچھے، یہ ہے IDs ذیلی استفسار سے واپس کردہ مواد کو مرکزی استفسار میں فیڈ کیا جاتا ہے، جس سے استفسار کو اس طرح تبدیل کیا جاتا ہے:
SELECT *
FROM registration
WHERE student_id
IN('STU1', 'STU13','STU2','STU4','STU23','STU27')
بنیادی سوال ہر قدر کا موازنہ کرتا ہے۔ student_id گرمی IDs ذیلی سوال کے طور پر واپس آیا۔ اگر کوئی مماثلت پائی جاتی ہے تو، طالب علم کی رجسٹریشن کی تفصیلات واپس کردی جاتی ہیں۔ ورنہ ریکارڈ نظر انداز کر دیا جائے گا۔
آپ سوچ رہے ہوں گے، "صرف تلاش کیوں نہیں؟” IDs کیا آپ اسے ذیلی استفسار استعمال کرنے کے بجائے اسٹوڈنٹ ٹیبل سے براہ راست مین استفسار پر منتقل کرنا چاہیں گے؟”
ٹھیک ہے، یہ مشکل کوڈنگ ہے. استفسار اب کام کر رہا ہے، لیکن بعد میں جب میرے پاس نئے طلباء ہوتے ہیں اور میں دوبارہ استفسار کرتا ہوں، تو مجھے صرف ان پرانے طلباء کی تفصیلات ملتی ہیں جن سے میں دستی طور پر گزرا تھا۔ IDs مرکزی استفسار پر جائیں۔ نئے کو خارج کر دیا گیا ہے۔
ذیلی سوال کا نقطہ نظر متحرک ہے۔ اس کا مطلب یہ ہے کہ طلباء کی میز سے مسلسل استفسار کیا جاتا ہے تاکہ یہ یقینی بنایا جا سکے کہ نتائج ہمیشہ تازہ ترین ہیں۔
سبکیری کی قسم
انحصار پر مبنی ذیلی سوالات کی دو قسمیں ہیں: غیر متعلقہ (آزاد) اور مربوط (انحصار)۔
غیر متعلقہ ذیلی استفسار
یہ ایک ذیلی استفسار ہے جو مرکزی استفسار سے آزاد ہے۔ یہ کام کرتا ہے اگر میں اسے مرکزی استفسار سے باہر چلاتا ہوں۔ ایک اچھی مثال وہ ہے جو اوپر کے استفسار میں استعمال کی گئی ہے۔
SELECT *
FROM registration
WHERE student_id
IN (SELECT
id
FROM student
WHERE location = 'Lagos')
یہ نوٹ کرنا ضروری ہے کہ ذیلی سوالات SQL استفسار کے دوسرے حصوں میں ظاہر ہو سکتے ہیں، قطع نظر اس سے کہ وہ متعلقہ ہیں یا نہیں۔ جہاں ذیلی استفسار ظاہر ہوتا ہے مرکزی استفسار میں اس کے کردار کا تعین کرتا ہے۔ یہ ایک اخذ کردہ کالم، اخذ کردہ ٹیبل، یا فلٹر کے طور پر کام کر سکتا ہے۔
آئیے ایک اہم سوال کے مختلف حصوں پر بات کرتے ہیں جہاں ذیلی استفسارات ظاہر ہو سکتے ہیں اور کس طرح ذیلی استفسارات مرکزی استفسار کی حمایت کرتے ہیں۔
1. ماخوذ کالم کے طور پر ذیلی استفسار
ذیلی استفسار کو دیکھتے ہوئے: SELECT بیان، ماخوذ کالم۔ اخذ کردہ کالم ٹیبل میں کسی دوسرے کالم کی قدروں کا استعمال کرتے ہوئے استفسار کے ذریعے تخلیق کردہ کالم ہے۔ یہ ڈیٹا بیس میں محفوظ نہیں ہے اور صرف استفسار کی مدت کے لیے موجود ہے۔
مثال کے طور پر، ہر کورس کے اندراج کے کل فیصد کا حساب لگانے کے لیے، آپ کو ایک ہی قطار میں معلومات کے تین ٹکڑوں کی ضرورت ہے:
شروع کرنے کے لیے، آپ ایک بنیادی استفسار لکھ سکتے ہیں جو تمام کورسز کے نام اور ہر کورس کے لیے اندراج کی تعداد لوٹاتا ہے۔
SELECT
course_name,
COUNT(reg_id) AS registrations
FROM course AS l
LEFT JOIN registration AS r
ON l.id = r.course_id
GROUP BY course_name
نتیجہ:

بنیادی استفسار ہر کورس کے اندراج کی تعداد کے ساتھ فہرست کرتا ہے۔ ہر کورس کے لیے کل اندراج کے فیصد کا حساب لگانے کے لیے، تمام کورسز کے لیے کل اندراج کو بھی اہم سوال کے نتائج کی ہر قطار میں شامل کیا جانا چاہیے۔
اس کو حاصل کرنے کے لیے، آپ ایک ذیلی استفسار کر سکتے ہیں جو تمام کورسز کے اندراجات کی کل تعداد کو بطور کالم مرکزی استفسار پر واپس کرتا ہے، جیسا کہ:
SELECT COUNT(reg_id) FROM registration
جب اس ذیلی استفسار کو مرکزی استفسار سے باہر انجام دیا جاتا ہے، تو یہ ذیل کے نتائج لوٹاتا ہے۔

30 تمام کورسز کے اندراج کی کل تعداد ہے۔ اب ذیلی سوال کو مرکزی سوال کا کالم بنانے کے لیے پہلے اسے مربع بریکٹ میں اس طرح بند کریں:
(SELECT COUNT(reg_id) FROM registration)
پھر ذیلی سوال کو مرکزی سوال کی کالم فہرست میں داخل کریں جیسا کہ ذیل میں دکھایا گیا ہے۔
SELECT
course_name,
COUNT(reg_id) AS regs,
(SELECT COUNT(reg_id) FROM registration) AS total --subquery
FROM course AS l
LEFT JOIN registration AS r
ON l.id = r.course_id
GROUP BY course_name
جب چلتا ہے، تو یہ درج ذیل نتائج دیتا ہے:

مندرجہ بالا جدول میں، بنیادی استفسار کورس کا نام اور اندراج کی گنتی کو عرف کے طور پر واپس کرتا ہے۔ regs. ذیلی استفسار ہے۔ total ایک کالم جس میں تمام کورسز کے اندراج کی کل تعداد (30) ہو۔ قیمت (30) نتائج کی ہر قطار میں ظاہر ہوتی ہے۔
کورس کے نام، اندراج کی تعداد، اور ہر قطار کے تمام کورسز کے لیے کل اندراج کا استعمال کرتے ہوئے، اب ہم ہر کورس کے لیے کل اندراج کے فیصد کا حساب لگا سکتے ہیں۔
سرکاری:
Percentage of Total = regs / total * 100
سب سے پہلے، دونوں regs اور total کالم میں عددی اقدار ہیں۔ اگر آپ براہ راست تقسیم کرتے ہیں، تو نتیجہ 0 ہوگا۔ اسے روکنے کے لیے، ہمیشہ FLOAT ڈیٹا کی اقسام کا استعمال کرتے ہوئے CAST() یہ مندرجہ ذیل کام کرتا ہے:
-- casting numerator to float data type
CAST(
COUNT(reg_id)
AS FLOAT)
مالیکیولز ڈالنے کے بعد FLOATمندرجہ ذیل تقسیم کے ساتھ آگے بڑھیں:
CAST(COUNT(reg_id) AS FLOAT) -- Numerator
/ -- Divide sign
(SELECT COUNT(reg_id) FROM registration) -- Denominator
* 100 -- Convert to percentage
آئیے یہ سب ایک ساتھ رکھیں:
SELECT
course_name,
CAST(COUNT(reg_id) AS FLOAT)/
(SELECT
COUNT(reg_id)
FROM registration) * 100 AS percent_of_total
FROM course AS l
LEFT JOIN registration AS r
ON l.id = r.course_id
GROUP BY course_name
اگر آپ مندرجہ بالا استفسار کو چلاتے ہیں، تو آپ کو درج ذیل نتائج ملیں گے:

نتائج تمام کورسز کو ان کے مجموعی اندراج کے فیصد کے ساتھ دکھاتے ہیں۔ کسی قدر میں اعشاریہ مقامات کی تعداد کو کنٹرول کرنے کے لیے percent_of_total کالم SQL استعمال کر سکتے ہیں۔ ROUND() یہ فنکشن ایک اعشاریہ کی جگہ پر ہوتا ہے۔ ذیل میں تازہ ترین استفسار دیکھیں۔
SELECT
course_name,
ROUND(CAST(COUNT(reg_id) AS FLOAT)/
(SELECT
COUNT(reg_id)
FROM registration) * 100,1) AS percent_of_total
FROM course AS l
LEFT JOIN registration AS r
ON l.id = r.course_id
GROUP BY course_name
نتیجہ:

آخر میں، آپ مجموعی اندراج میں ہر کورس کی شراکت دیکھ سکتے ہیں۔
2. ماخوذ جدولوں کے طور پر ذیلی سوالات
ذیلی استفسار کو دیکھتے ہوئے: FROM شق، اخذ کردہ جدول۔ اخذ کردہ ٹیبل ایک عارضی جدول ہے جو استفسار کے نتائج سے بنائی گئی ہے۔ وہ ڈیٹا بیس میں مستقل طور پر محفوظ نہیں ہوتے ہیں اور استفسار کے چلنے کے وقت ہی موجود رہتے ہیں۔
مثال کے طور پر، ہم کہتے ہیں کہ آپ ایک سوال لکھ رہے ہیں جو علاقے کے لحاظ سے طلباء کی تعداد لوٹاتا ہے۔
تاہم، اگر آپ نیچے دیے گئے استفسار کا استعمال کرتے ہوئے اسٹوڈنٹ ٹیبل سے استفسار کرتے ہیں:
SELECT * FROM student
آپ نے پایا کہ یہ وہاں نہیں تھا۔ regionاس کے بجائے state گرمی:

اس مسئلے کو حل کرنے کے لیے، آپ درج ذیل اقدار کو استعمال کر سکتے ہیں۔ state کالم جو اخذ کرتے ہیں۔ region ایس کیو ایل کا استعمال کرتے ہوئے کالم CASE بیانات جیسے:
SELECT
*, -- all columns of the student table
CASE
WHEN location
IN('Abeokuta','Ibadan','Mokola','Iyana Ipaja','Lagos')
THEN 'West'
WHEN location
IN('Anambra','Owerri','Enugu','Port Harcourt')
THEN 'East'
WHEN location
IN('Abuja','Ilorin','Kaduna','Kano','Jos')
THEN 'North'
END AS region -- a derived region column
FROM student
جب مندرجہ بالا استفسار پر عمل کیا جاتا ہے، تو ذیل کے نتائج واپس آ جاتے ہیں۔

نتائج اب اسٹوڈنٹ ٹیبل کے تمام کالم دکھاتے ہیں، بشمول ریجن کالم جو استعمال کرتے ہوئے بنایا گیا ہے: CASE نام
اب جب کہ ہمارے پاس ایک مقامی کالم ہے، آئیے پوری استفسار کو ٹیبل کے ذیلی سوال میں تبدیل کرتے ہیں۔
سب سے پہلے، پوری استفسار کو قوسین میں بند کریں اور اسے ایک عرف دیں:
(SELECT
*,
CASE
WHEN location
IN('Abeokuta','Ibadan','Mokola','Iyana Ipaja','Lagos')
THEN 'West'
WHEN location
IN('Anambra','Owerri','Enugu','Port Harcourt')
THEN 'East'
WHEN location
IN('Abuja','Ilorin','Kaduna','Kano','Jos')
THEN 'North'
END AS region
FROM student) AS data_prep -- aliased data_prep
استعمال کرنا data_prepبریکٹ اور عرفی ناموں سمیت مکمل استفسار FROM شق ایک باقاعدہ میز کی طرح ہے:
FROM (SELECT
*,
CASE
WHEN location
IN('Abeokuta','Ibadan','Mokola','Iyana Ipaja','Lagos')
THEN 'West'
WHEN location
IN('Anambra','Owerri','Enugu','Port Harcourt')
THEN 'East'
WHEN location
IN('Abuja','Ilorin','Kaduna','Kano','Jos')
THEN 'North'
END AS region
FROM student) AS data_prep
اس لمحے سے، آپ منتخب کر سکتے ہیں کہ آپ کون سا ڈیٹا چاہتے ہیں: data_prep. یہ ایک باقاعدہ میز کی طرح کام کرتا ہے۔
اب آئیے درج ذیل ڈیٹا کا استعمال کریں: data_prep علاقے کے لحاظ سے طلباء کی تعداد کا حساب لگانے کے لیے:
SELECT
region,
COUNT(id) AS students
FROM (SELECT
*,
CASE
WHEN location
IN('Abeokuta','Ibadan','Mokola','Iyana Ipaja','Lagos')
THEN 'West'
WHEN location
IN('Anambra','Owerri','Enugu','Port Harcourt')
THEN 'East'
WHEN location
IN('Abuja','Ilorin','Kaduna','Kano','Jos')
THEN 'North'
END AS region
FROM student) AS data_prep
GROUP BY region
جب مندرجہ بالا استفسار پر عمل کیا جاتا ہے، تو ذیل کے نتائج واپس آ جاتے ہیں۔

نتائج علاقے کے لحاظ سے طلباء کی تعداد ظاہر کرتے ہیں۔
3. فلٹر کے طور پر ذیلی سوالات
ذیلی استفسار کو دیکھتے ہوئے: WHERE شق، جو بنیادی سوال کے لیے فلٹر ہے۔ آپریٹرز کے مختلف گروپس ہیں جن کا استعمال بنیادی سوالات کو فلٹر کرنے کے لیے کیا جا سکتا ہے۔
منطقی آپریٹرز
ان میں شامل ہیں: IN, ANYاور ALL. جب ایک ذیلی استفسار ایک سے زیادہ قدریں لوٹاتا ہے، تو آپ اسے اپنے ڈیٹاسیٹ میں کالم کی قدروں کا موازنہ ذیلی استفسار کے ذریعے لوٹائی گئی اقدار کے ساتھ کر سکتے ہیں۔
میں نے استعمال کرتے ہوئے مثالیں دیکھی ہیں: IN اس سے پہلے باقی دو کی طرف چلتے ہیں۔
منظر نامہ: آپ مرد طلباء کے ریکارڈز بازیافت کرتے ہیں جو خواتین طلباء سے زیادہ عمر کے ہیں۔ اس کو حاصل کرنے کے لیے اسے استعمال کرنے کا طریقہ ذیل میں ہے۔ ANY:
SELECT
*
FROM student
WHERE gender="Male"
AND age > ANY (SELECT
DISTINCT age
FROM student
WHERE gender="Female")
مندرجہ بالا استفسار دو حصوں پر مشتمل ہے: مین استفسار اور ذیلی استفسار۔
اہم سوال یہ ہے:
SELECT
*
FROM student
WHERE gender="Male"
AND age > ANY (...)
اور ذیلی استفسار یہ ہے:
SELECT
DISTINCT age
FROM student
WHERE gender="Female"
مینجمنٹ سسٹم پر مکمل استفسار چلانا اس طرح نظر آئے گا:
SELECT
*
FROM student
WHERE gender="Male"
AND age > ANY (SELECT
DISTINCT age
FROM student
WHERE gender="Female")
پردے کے پیچھے، ذیلی سوالات کا پہلے جائزہ لیا جاتا ہے۔
SELECT
DISTINCT age
FROM student
WHERE gender="Female"
ذیلی سوال طالب علم کی میز سے طالب علم کی الگ الگ عمریں لوٹاتا ہے۔

ذیلی استفسار کے نتائج مرکزی استفسار پر بھیجے جاتے ہیں، جس کے نتیجے میں مکمل استفسار ہوتا ہے جیسا کہ ذیل میں دکھایا گیا ہے۔
SELECT
*
FROM student
WHERE gender="Male"
AND age > ANY (23, 25, 26, 27, 28, 29, 30)
اب ہر لڑکے کی عمر کا موازنہ لڑکی کی عمر سے کیا جاتا ہے بنیادی استفسار صرف ان لڑکوں کو لوٹاتا ہے جو لڑکیوں کی عمروں میں سے کم از کم ایک سے بڑے ہیں۔

نتائج ان لڑکوں کی تفصیلات دکھاتے ہیں جن کی عمر کم از کم ایک لڑکی سے زیادہ ہے۔
مذکورہ سوال میں ANY آپریٹر کو اس بات کو یقینی بنانا چاہیے کہ لڑکا طالب علم کم از کم ایک طالب علم سے بڑا ہے تاکہ اس کے ریکارڈز کو ڈیفالٹ استفسار کے ذریعے واپس کیا جائے۔
کے ساتھ ALLچیزیں تھوڑی مختلف طریقے سے کام کرتی ہیں۔ لڑکوں کی عمر زیادہ ہونی چاہیے۔ ہر لڑکیوں نے اس کا ریکارڈ واپس مانگا۔ استعمال کرتے ہوئے ایک مثال سوال دیکھیں: ALL ذیل میں:
SELECT
*
FROM student
WHERE gender="Male"
AND age > ALL (SELECT
DISTINCT age
FROM student
WHERE gender="Female")
نتیجہ:

استفسار سے واحد مرد طالب علم واپس آیا جو تمام طالبات سے زیادہ عمر کا تھا۔
موازنہ آپریٹر
اس کا استعمال ایک کالم کی قدر کا موازنہ کرنے کے لیے کیا جاتا ہے جو ایک ذیلی استفسار سے واپس کی گئی ایک اسکیلر قدر کے ساتھ ہوتا ہے۔ ان میں شامل ہیں:
-
جیسا کہ (==)
-
(>) سے بڑا
-
(>=) سے زیادہ
-
(<) سے کم
-
(=<) سے کم یا اس کے برابر
-
(<> یا !=) کے برابر نہیں
مثال کے طور پر، ہم کہتے ہیں کہ آپ ان طلباء کی تفصیلات بازیافت کرنا چاہتے ہیں جو تمام طلباء کی اوسط عمر سے زیادہ ہیں۔ ذیل میں استفسار دیکھیں۔
SELECT *
FROM student
WHERE age > (SELECT AVG(age) FROM student)
جب استفسار کیا جاتا ہے، تو یہ ان طلباء کی تفصیلات لوٹاتا ہے جو تمام طلباء کی اوسط عمر سے زیادہ ہیں۔

آئیے سوالات کے عمل درآمد کے حکم کے بارے میں بات کرتے ہیں۔
جب آپ مکمل استفسار پہلے چلاتے ہیں، سب سے پہلے پس منظر میں ذیلی سوالات کا جائزہ لیا جاتا ہے۔
SELECT AVG(age) FROM student
ذیلی سوال ایک واحد قدر، 25 لوٹاتا ہے، جو کہ تمام طلباء کی اوسط عمر ہے۔

اگر ذیلی سوال 25 کی قدر لوٹاتا ہے، تو اندرونی طور پر پوری استفسار ذیل کی طرح نظر آئے گی:
SELECT * FROM student WHERE age > 25
مرکزی استفسار سٹوڈنٹ ٹیبل میں ہر طالب علم کی عمر کا موازنہ ذیلی استفسار کے ذریعے واپس کیے گئے 25 سے کرتا ہے۔ اگر کسی طالب علم کی عمر 25 سال سے زیادہ ہے تو ان کے ریکارڈ کو نتائج میں شامل کیا جائے گا۔ ورنہ نظر انداز کر دیا جائے گا۔
ذیل میں اہم سوال کے نتائج دیکھیں۔ عمر کے کالم میں تمام اقدار 25 سے زیادہ ہیں۔

آپ موازنہ آپریٹرز کو بھی تبدیل کر سکتے ہیں اس پر منحصر ہے کہ آپ کیا دیکھنا چاہتے ہیں۔ مختلف موازنہ آپریٹرز کے لیے استعمال کے کچھ معاملات یہ ہیں:
-- retrieve students whose age is greater or equal to the average age of all students
SELECT *
FROM student
WHERE age >= (SELECT AVG (age) FROM student)
-- retrieve students whose age is less than the average age of all students
SELECT *
FROM student
WHERE age < (SELECT AVG (age) FROM student)
-- retrieve students whose age is less than or equal the average age of all students
SELECT *
FROM student
WHERE age =< (SELECT AVG (age) FROM student)
-- retrieve students whose age is equal to the average age of all students
SELECT *
FROM student
WHERE age = (SELECT AVG (age) FROM student)
-- retrieve student whose age is not equal to the average age of all students
SELECT *
FROM student
WHERE age <> (SELECT AVG (age) FROM student)
--Alternatively, you can also use !=, which stands for not equal to
SELECT *
FROM student
WHERE age != (SELECT AVG (age) FROM student)
متعلقہ ذیلی استفسار
اس قسم کی ذیلی استفسار کام کرنے کے لیے مرکزی استفسار کی اقدار پر منحصر ہے۔ اگر آپ اسے مرکزی استفسار سے باہر چلاتے ہیں تو یہ کام نہیں کرتا ہے۔
مثال کے طور پر، فرض کریں کہ آپ ہر کورس کے لیے اندراج کی تعداد کا حساب لگانے کے لیے ایک متعلقہ ذیلی استفسار استعمال کرنا چاہتے ہیں۔
سب سے پہلے، آئیے ایک سوال کے ساتھ شروع کریں جس میں تمام کورسز کے اندراج کی کل تعداد کو واپس کرنے کے لیے کالم کے طور پر غیر متعلقہ ذیلی سوالات شامل ہوں۔
SELECT
course_name,
(SELECT COUNT(reg_id) FROM registration) AS regs --subquery
FROM course
جب عمل میں لایا جاتا ہے، تو مرکزی استفسار ہر کورس کا نام اس سے بازیافت کرتا ہے: course ذیلی سوال ٹیبل میں رجسٹریشن کی کل تعداد کو شمار کرتا ہے۔ registration میز ذیلی استفسار کے نتائج اخذ کردہ کالم کے طور پر واپس کیے جاتے ہیں اور course_name. ذیل میں نتائج دیکھیں۔

تاہم، مندرجہ بالا نتیجہ وہ نہیں ہے جس کی ہمیں ضرورت ہے۔ ہم اصل میں چاہتے ہیں کہ ہر کورس کے لیے رجسٹریشن کی تعداد تمام کورسز کے لیے رجسٹریشن کی کل تعداد کے بجائے اس کے آگے دکھائی جائے۔
اس مسئلے کو حل کرنے کے لیے، ہم ابتدائی غیر متعلقہ ذیلی استفسار کو بنیادی استفسار میں موجود اقدار کی بنیاد پر فلٹر میں تبدیل کر کے اسے ایک مربوط ذیلی استفسار میں تبدیل کر دیتے ہیں۔
غیر متعلقہ ذیلی سوالات یہاں دیکھیں۔
(SELECT COUNT(reg_id) FROM registration) AS regs
متعلقہ ذیلی استفسار کے ساتھ مذکورہ ذیلی استفسار کو اپ ڈیٹ کرنے کے لیے:
سب سے پہلے، اس پورے استفسار کو کاپی کریں جو ہم نے پہلے استعمال کیا تھا اور مرکزی استفسار اور ذیلی سوالات میں ٹیبلز کو عرفی نام تفویض کریں۔
-- Alias the course table l and registrations as r
SELECT
course_name,
(SELECT COUNT(reg_id) FROM registration AS r) AS regs
FROM course AS l
اگلا، مرکزی استفسار میں موجود ٹیبلز کو ذیلی استفسار میں موجود جدولوں سے یہ استعمال کرتے ہوئے لنک کریں: id کورس ٹیبل میں کالم course_id رجسٹریشن ٹیبل میں کالم یہ ہیں:
SELECT
COUNT(reg_id)
FROM registration AS r
WHERE r.course_id = l.id -- the connection
اب مندرجہ بالا ذیلی استفسار ایک متعلقہ ذیلی سوال ہے۔ اگر آپ اسے مرکزی استفسار سے الگ چلاتے ہیں، تو آپ کو ذیل کے نتائج ملیں گے:

یہ غلطی سادہ سی ہے۔ l.id پر WHERE ذیلی استفسار میں شقوں کو تسلیم نہیں کیا گیا ہے کیونکہ وہ بنیادی استفسار سے آتے ہیں۔
اس کے کام کرنے کے لیے اسے بنیادی استفسار میں کالم کے طور پر نیسٹ کیا جانا چاہیے۔ ذیل میں مکمل استفسار دیکھیں۔
SELECT
course_name,
(SELECT
COUNT(reg_id)
FROM registration AS r
WHERE r.course_id = l.id) AS regs -- correlated subquery
FROM course AS l
جب عمل درآمد کیا جاتا ہے، تو ذیل کے نتائج واپس آ جاتے ہیں۔

مندرجہ بالا نتائج ہر مضمون کے لیے مضامین کے نام اور رجسٹریشن کی تعداد کو ظاہر کرتے ہیں۔
اب آئیے استفسارات کے نفاذ کے حکم کو دیکھتے ہیں۔
جب پوری استفسار پر عمل درآمد کیا جاتا ہے، تو پہلے پس منظر میں مرکزی سوال کا جائزہ لیا جاتا ہے۔
SELECT
course_name
FROM course AS l
پہلے سے طے شدہ استفسار صرف ایک بار چلانے کے بجائے تمام کورس کے نام لوٹاتا ہے۔ اس کے بجائے، یہ ایک وقت میں ایک کورس کے نام لوٹاتا ہے۔ مزید برآں، مرکزی استفسار کے ذریعے واپس کیے گئے ہر کورس کے نام کے لیے، اس مخصوص کورس کے لیے ایک ذیلی استفسار کیا جاتا ہے۔
مثال کے طور پر، مکمل استفسار کے پہلے تکرار کے دوران، مرکزی استفسار کے ذریعہ واپس کردہ پہلا کورس کا نام ڈیٹا تجزیہ تھا، اور اس کی ID یہ ہے: CS01. پھر بنیادی سوال دیتا ہے: CS01 ذیلی سوال کو نیچے کے منظر کی طرح بنائیں۔
SELECT
COUNT(reg_id)
FROM registration AS r
WHERE r.course_id = CS01 -- ID for data analytics
مندرجہ بالا ذیلی استفسار صرف ان رجسٹریشنوں کو شمار کرے گا جن کا course_id مرکزی سوال میں فراہم کردہ قدر سے میل کھاتا ہے (اس معاملے میں CS01)۔ اس کے بعد رجسٹریشن کی تعداد کورس کے نام کے ساتھ واپس کردی جاتی ہے۔
اگلی تکرار میں
-
بنیادی استفسار کورس کا نام بازیافت کرتا ہے اور کورس کو واپس کرتا ہے۔
IDایک ذیلی استفسار میں۔ -
ذیلی سوال اس مخصوص کورس کے لیے اندراج کی تعداد کو شمار کرتا ہے۔
-
رجسٹریشن کی تعداد کورس کے نام کے آگے ظاہر ہوتی ہے۔
یہ عمل اس وقت تک جاری رہتا ہے جب تک کہ تمام بنیادی استفسار ٹیبلز پر کارروائی نہیں ہو جاتی۔ بنیادی طور پر، ٹیبل میں کورسز کی تعداد اس بات کا تعین کرتی ہے کہ استفسار کتنی تکرار کرے گا۔
ذیل میں حتمی نتائج دیکھیں۔

حتمی نتیجہ رجسٹریشن کی تعداد کے ساتھ تمام کورس کے نام دکھائے گا۔ وہ کورسز جن کے لیے ابھی تک کوئی رجسٹریشن نہیں ہے 0 کے طور پر دکھایا گیا ہے۔
آپریٹر موجود ہے۔
EXISTS چیک کرتا ہے کہ آیا متعلقہ ٹیبل میں مماثل قطار موجود ہے اور اسے لوٹاتا ہے۔ TRUE جب کوئی مل جاتا ہے۔ FALSE اگر کچھ نہ ملے۔
مثال کے طور پر، ایسے کورسز کی نشاندہی کرنا جن میں کم از کم اندراج ہے:
SELECT
course_name
FROM course AS l
WHERE EXISTS (SELECT 1
FROM registration AS r
WHERE r.course_id = l.id)
مندرجہ بالا استفسار ایک اہم سوال اور ایک متعلقہ ذیلی استفسار پر مشتمل ہے۔
اہم سوال یہ ہے:
SELECT
course_name
FROM course AS l
WHERE EXISTS (...)
اوپر دیے گئے بنیادی سوال میں، کوئی سابقہ کالم کا نام نہیں ہے۔ EXISTS آپریٹر یہ ہے EXISTS مرکزی استفسار کے کالموں میں موجود اقدار کا موازنہ ذیلی استفسار کے ذریعہ واپس کی گئی اقدار سے نہیں کیا جاتا ہے۔ اس کے بجائے، EXISTS چیک کریں کہ آیا ذیلی سوال کم از کم ایک قطار لوٹاتا ہے۔ اس کا اندازہ اس طرح کیا جاتا ہے: TRUE جب ایک صف مل جائے۔ FALSE اگر قطار نہیں ملتی ہے:
SELECT 1
FROM registration AS r
WHERE r.course_id = l.id
ذیلی سوال کا کردار رجسٹریشن ٹیبل کو چیک کرنا ہے۔ ID مرکزی سوال کے ذریعہ ایک رجسٹریشن فراہم کی گئی ہے۔ ذیلی استفسار میں SELECT کا بیان کوئی کالم درج نہیں دکھاتا ہے، صرف پلیس ہولڈر 1۔ یہ اس لیے استعمال ہوتا ہے کیونکہ ذیلی استفسار کے ذریعے لوٹائی گئی اصل قیمت غیر متعلقہ ہے۔ اہم بات یہ ہے کہ آیا صف موجود ہے۔
اب جب کہ ہم نے استفسار کے ڈھانچے پر بات کی ہے، آئیے دیکھتے ہیں کہ استفسار کے عمل کو کیسے سمجھنا ہے۔
آئیے پورے سوال کو دوبارہ دیکھتے ہیں۔
SELECT
course_name
FROM course AS l
WHERE EXISTS (SELECT 1
FROM registration AS r
WHERE r.course_id = l.id)
ایک بار جب اوپر دی گئی پوری استفسار پر عمل درآمد ہو جائے گا، تو جائزہ پس منظر میں شروع ہو جائے گا۔ FROM میں:
FROM course AS l
پھر کورس ٹیبل کی پہلی قطار پر غور کریں اور EXISTS چیک کرتا ہے کہ آیا ذیلی سوال میں مماثل قطاریں ہیں۔
WHERE EXISTS (SELECT 1
FROM registration AS r
WHERE r.course_id = l.id)
اب فرض کریں کہ کورس ٹیبل میں زیر غور پہلی قطار ڈیٹا کے تجزیہ اور اس قطار سے ہے۔ ID ہے CS01. یہ ID اسے ذیلی استفسار کے طور پر پاس کیا گیا ہے، لہذا ذیلی استفسار نیچے کی طرح نظر آتا ہے۔
SELECT 1
FROM registration AS r
WHERE r.course_id = CS01 --- ID for data analytics
قدر CS01 اس کا موازنہ کی قدر سے کیا جاتا ہے۔ course_id یہ رجسٹریشن ٹیبل میں ایک کالم ہے۔ جب ایک مماثل قطار مل جائے۔ EXISTS تشخیص TRUE بنیادی استفسار کے ذریعے واپس کیے گئے کورسز میں ڈیٹا کا تجزیہ شامل ہے۔
دیکھیں کیسے EXISTS درج ذیل شرائط کا اندازہ کریں:
EXISTS → TRUE → course included
لیکن اگر ID ذیلی سوال کو فراہم کردہ نتائج میں کوئی مماثل قطاریں نہیں ملیں۔ course_id رجسٹریشن ٹیبل میں کالم، EXISTS تشخیص FALSE کورس کے نام نتائج میں شامل نہیں ہیں۔
براہ کرم ذیل میں تشخیص کا بہاؤ دیکھیں۔
EXISTS → FALSE → course excluded
یہ عمل مرکزی سوال میں ہر قطار کے لیے جاری رہتا ہے جب تک کہ تمام قطاروں کا جائزہ نہ لیا جائے۔ نیچے پوری استفسار کا حتمی نتیجہ دیکھیں۔

نتائج کم از کم ایک اندراج کے ساتھ تمام کورسز دکھائیں گے۔
اگر آپ ان لوگوں کو دکھانا چاہتے ہیں جنہوں نے ابھی تک رجسٹر نہیں کیا ہے؟
SELECT
course_name
FROM course AS l
WHERE NOT EXISTS (SELECT 1
FROM registration AS r
WHERE r.course_id = l.id)
شامل کرکے NOT پہلے EXISTSحالات کو الٹ دیں۔ ایک یا زیادہ اندراج کے ساتھ کورسز واپس کرنے کے بجائے، استفسار بغیر اندراج کے کورسز واپس کرتا ہے۔

نتائج دو کورسز دکھاتے ہیں جن کے لیے ابھی تک کوئی رجسٹریشن نہیں ہے۔
نتیجہ
ذیلی استفسارات پہلے مشکل لگ سکتے ہیں، خاص طور پر جب کسی بڑے استفسار کے اندر اندر اندر بنایا گیا ہو۔ لیکن سب سے پہلے، مقصد صرف ہے اہم سوالات کی حمایت کرتا ہے۔یہ کام کرنا بہت آسان بناتا ہے۔
اہم بات یہ نہیں ہے کہ ہر ممکنہ ذیلی سوال کے نمونے کو یاد رکھیں۔ اس کے بجائے اسے پہچاننا سیکھیں۔ مرکزی استفسار کی کیا ضرورت ہے اور ذیلی سوالات اسے کیسے فراہم کرتے ہیں۔. اس طرزِ فکر کے ساتھ، اخذ کردہ کالم، اخذ کردہ جدول، IN, EXISTSاور NOT EXISTS یہ پیچیدہ SQL نحو کی بجائے ایک عملی ٹول بن جاتا ہے۔
کافی مشق کے ساتھ، آپ ذیلی سوالات کو SQL کی پیچیدہ خصوصیات کے طور پر کم اور زیادہ پیچیدہ سوالات کا تجزیہ کرنے اور حل کرنے کے قدرتی طریقے کے طور پر دیکھنا شروع کر دیں گے۔