PDA

نسخه کامل مشاهده نسخه کامل : تجزیه یک کوئری و توضیح آن



Life24
07-04-2014, 19:09
سلام
اماک نداره بفرمائید از داخل ترین select در هر مرحله چه چیزی خروجی میده؟

select distinct s.sname from s
where not exists
(select * from p
where not exists
(select * from spj
where SPJ.s# = s.s# and spj.p# = p.p#))


من متوجه نمیشم هر کاری میکنم.
این هم رابطه ها

S(s#,sname,city)

p(p#,pname,color)

j(j#,jname,city)

SPJ(S#,p#,j#,qty)

_H2_
09-04-2014, 15:25
سلام
در این مورد فرض کنید با دو(یاسه) حلقه for تو در تو طرف هستید.
گمانم اگر دو select اولی را دو حلقه فرض کنید که به تعداد سطرهایشان تکرار موشوند درک این کد ساده تر میشود.

قراردادهای متنی ذیل
SELECT * FROM s
اولین select = بیرونی ترین select

SELECT * FROM p
دومین select = select وسط

SELECT * FROM spj
سومین select = داخلی ترین select

در پایان هر نتیجه گیری مطمئن شوید که آن را فهمیده و درک کرده اید و سپس به خواندن ادامه دهید.

==============

فرض کنید جدول s کلاً یک سطر دارد !
میخواهیم ببینیم چه زمانی و با حصول چه شرایطی این سطر در خروجی بیرونی ترین select ظاهر شده و در چه شرایطی غربال و حذف میشود و در خروجی حضور نخواهد داشت.
بعد میتوان همین را تعمیم داده به کلیه سطرهای دیگر جدول s
ولی فعلاً فرض کنید جدول s فقط یک سطر دارد با شاخص کلید 123 دارد ...

نتیجه A:
مشخص است که این یک سطر زمانی در خروجی ظاهر میشود که دستور زیر هیچ سطری برنگرداند به بیان رایانه ای تر Count=0 باشد.

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
حل است؟! مشکلی که نیست؟!

اینجا با یک حلقه شبه for طرف هستیم که دستور select آخری را هر بار برای تک تک سطرهای p اجرا و خروجی آن تحلیل میکند.

کلاً دو حالت در دستور فوق داریم...
یا کلید (#p) جدول p در جدول spj موجود است؟ یا نیست؟
اگر کلید p در کنار 123 در جدول spj یافت شود ، select سوم چیزی برمیگرداند که باعث میشود Select دوم چیزی پس ندهد.

نتیجه B:
اگر کلید p در کنار 123 در جدول spj موجود نباشد، select سوم چیزی برنمیگرداند که باعث میشود Select دوم چیزی برگرداند.

تا اینجا که مشکل نداریم؟؟؟ اگر مشکلی است متن بالا را مجدد بخوانید و مطمئن شوید مئسله برایتان حل شده...

با توجه به نتیجه A تک تک سطرهای select میانی برایمان مهم نیست!
مهم آن است که آیا select * from p کلاً روی همه سطرهای p چیزی بر میگرداند یا نه؟!

پس نتیجه B را که برای تک تک سطرهای p بود تعمیم میدهیم به کل select میانی روی p که چه زمانی خروجی دارد و چه زمانی ندارد.

نتیجه C:
اگر حتی یک کلید جدول p در کنار 123 در جدول spj موجود نباشد، باعث میشود select دوم چیزی برگرداند.

اگر همه کلیدهای جدول p در کنار 123 در جدول spj موجود باشند، آنگاه select دوم کلاً هیچ سطری بر نمیگرداند.

باز مجدد متن بالا را خوانده و مطمئن شوید که متوجه شده اید و در آن شک و شبه ای ندارد وگرنه مجدد خواندن را تکرار کنید.

اگر کمکی میکند دستور قبلی، تقریباً با دستور زیر برابر است و اگر فکر میکنید کار را پیچیده تر میکند حداقل فعلاً بیخیال دستور زیر شوید!

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

==============

نتیجه نهایی:

از کنار هم گذاشتن نتیجه C و نتیجه A میتوان گفت:

اگر حتی یک کلید جدول p در کنار 123 در جدول spj موجود نباشد، باعث میشود select اول چیزی برنگرداند.

اگر همه کلیدهای جدول p در کنار 123 در جدول spj موجود باشند، آنگاه select اول، آن یک سطر داخل s را برمیگرداند.


پس روشن شد، سطرهایی در خروجی select اول و نهایی می آیند که #s آنها با تمام #p های موجود در جدول spj رابطه داشته باشند و در کنار هم باشند.
مثلاً اگر جدول p یکصد سطر داشته باشد، باید #s هم یکصد سطر با تک تک #p ها در spj داشته باشد تا در خروجی ظاهر شود.

==============

در نهایت لازم به گفتن نیست که distinct s.sname باعث میشود فقط نام های جدول s آن هم بصورت غیر تکراری در خروجی ظاهر شود.
موفق باشید.