PDA

View Full Version : بهینه کردن یک Subquery



Mahyaa
پنج شنبه 24 اردیبهشت 1388, 12:07 عصر
جدولی داریم با نام tbl_Process


Id int
Name Varchar(30)
PreviousProc int
ParentProc int
کوئریی میخوام که رکوردهای با این مشخصات رو برگردونه :
رکوردهایی رو که PreviousProc آنها برابر مقدار 4 هست + رکوردهایی که ParentProc آنها برابر هرکدام از رکوردهای بازگردانده شده از بخش اول باشد.


Select Id , Name From tbl_Process Where
PreviousProc = 4
OR
ParentProc In
(Select Id , Name From tbl_Process Where PreviousProc = 4 )
چنین چیزی رو نوشتم ولی میخوام اگه بشه بهینه اش کنم.راه بهتری وجود نداره ؟

کسی میتونه من رو راهنمایی کنه

amin_alexi
پنج شنبه 24 اردیبهشت 1388, 20:45 عصر
سلام
اینQuery که شما نوشتید فکر نکنم اصلا کار کنه که بخواید یک بهینه براش بنویسید


OR
ParentProc In
(Select Id , Name From tbl_Process Where PreviousProc = 4 )این جاکه می خواید مقدار ParentProc رو در یک یک SubQuery باشه باید SubQuery شما فقط یک فیلد داشته باشه .... به کد من دقت کنید ....

Select Id, Name From tbl_Process
Where PreviousProc = 4
Union ALL
Select Id , Name From tbl_Process Where
ParentProc In
(Select ParentProc From tbl_Process
Where PreviousProc = 4 )اگه درست فهمیده باشد باشم این منظور شماست ... و گرنه توضیح بیشتر بدید !

Mahyaa
یک شنبه 27 اردیبهشت 1388, 18:42 عصر
در مورد Subquery حق با شماست. چون کوئری اول رو کپی پیست کردم فراموش کردم اون فیلد اضافی رو پاک کنم باید این رو مینوشتم :


Select Id , Name From tbl_Process Where
PreviousProc = 4
OR
ParentProc In
(Select Id From tbl_Process Where PreviousProc = 4 )


اما من نیاز به Union ندارم چون تمام رکوردها رو از یک جدول میگیرم. چیزی که من توی این کوئری باهاش کنار نمیام اینه که باید دوبار به یک جدول کوئری بزنم یک بار در بدنه اصلی و یکبار هم در SubQuery .

این راهی نداره ؟

amin_alexi
دوشنبه 28 اردیبهشت 1388, 09:13 صبح
اما من نیاز به Union ندارم چون تمام رکوردها رو از یک جدول میگیرم
می تونم بپرسم چرا؟
ببینید وقتی یک فیلد از یک جدول با یک فیلد دیگه از همون جدول ارتباط داشته باشه (مثل این حالت شما که یک ارتباط Parent , Child وجود داره) حتما مجبورید از Join جدول با خودش یا استفاده از یک SubQuery از خود جدول و یا از همین مدلی که من گفتم (استفاده از Union) استفاده کنید اصلا عبارت Self Join به همین خاطره که بعضی موارد لازمه که یک جدول با خودش Join بشه (شرط Join هم اینه PreviousProc = ParentProc) !
در ضمن شما در SubQuery باید به جای استفاده از ID از ParentProc استفاده کنید چون خروجی Id هایی که در SubQuery در میاد در همون Query اول هست و روی نتیجه Query تاثیری نداره ! این هم شبیه سازی Join می باشد !

Select Id , Name From tbl_Process Where
PreviousProc = 4
OR
ParentProc In
(Select ParentProc From tbl_Process Where PreviousProc = 4 )
امید وارم حالا باهاش کنار بیاین ! :چشمک:

Mahyaa
سه شنبه 29 اردیبهشت 1388, 12:47 عصر
خیلی ممنون که وقت میگذارید. اما صورت مساله من رو که نمیخواهید عوض کنید ؟!

کوئری که من نوشتم ممکنه اشکال ساختاری داشته باشه (در واقع سوال من هم همینه) اما حاصل رو صحیح بر میگردونه
اگر به پست اول من توجه کنید میبینید که من گفتم :


رکوردهایی رو که PreviousProc آنها برابر مقدار 4 هست + رکوردهایی که ParentProc آنها برابر هرکدام از رکوردهای بازگردانده شده از بخش اول باشد.

که کوئری که شما زحمتش رو کشیدید این رکوردهای خواسته شده را برنمیگردونه.

Union هم به نظر منطقی نمیاد به دلیل اینکه کوئری از یک جدول هست و با Where هم من همون نتیجه رو گرفتم. Union چه کمکی میکنه ؟

در مورد Self Join فکر میکنم شاید جواب من باشه ولی دقیقا نمیدونم چطوری باید Join بزنم. در هر صورت اگر کسی بتونه به من بگه که آیا این کوئری که من نوشتم یهترین حالت هست یا نه واگر نیست راه حلش چیه ، کلی دعاش میکنم : )

ممنون

amin_alexi
چهارشنبه 30 اردیبهشت 1388, 10:59 صبح
Union هم به نظر منطقی نمیاد به دلیل اینکه کوئری از یک جدول هست و با Where هم من همون نتیجه رو گرفتمهر چند خیلی بعید می دونم با همون Query که نوشتید همون نتیجه ای رو بگیرید که با Union گرفتید! (البته اگه Union رو اجرا کرده باشید!)
چرا فکر می کنید چون دارید از یک جدول Query میگیرید نباید از Union استفاده کنید !
شما در حقیقت دو جدول دارید ! که با هم ادقام شدند در حالت نرمال سازی نباید یک فیلد از یک جدول با فیلد دیگه ارتباط داشته باشه! (طراحی اشتباه جداول همین روزها آدم رو کلافه می کنه که من چرا باید برای گرفتن اطلاعات از یک جدول یک SubQuery با خود جدول بزنم یا Union کنم )
حالت سون نرمال سازی ( 3nf ) میگه : باید 2nf بوده و صفات خاصه غیرکلید باهم رابطه نداشته باشند ... که در جدول شما این ارتباط وجود داره ( PreviousProc و ParentProc )
(امید وارم حالا با این توضیحات با این موضوع که گفتید کنار بیاین!!

اما من نیاز به Union ندارم چون تمام رکوردها رو از یک جدول میگیرم. چیزی که من توی این کوئری باهاش کنار نمیام اینه که باید دوبار به یک جدول کوئری بزنم یک بار در بدنه اصلی و یکبار هم در SubQuery .
)
در کل فکر میکنم توضیحی که در post شماره 4 دادم خیلی کامل بود واین Post کاملتر !!!
(شرط Self join رو هم گفتم خودتون به راحتی می تونید اون Join رو بزنید ) و به احتمال زیاد باید جواب می داد !
شاید هم من خوب ساختار جدولتون رو متوجه نشدم (که با توجه به Query شما چیزی غیر از این نبود!)
اکه می خوای یک Script با Data بزار تا ببینم چه کار میشه کرد !
شما Self join رو بنویس اگه مشکل داشتی بگو

amin_alexi
چهارشنبه 30 اردیبهشت 1388, 11:01 صبح
اما صورت مساله من رو که نمیخواهید عوض کنید ؟!راستی من کجا صورت مساله شما رو عوض کردم ! :لبخند:

Mahyaa
چهارشنبه 30 اردیبهشت 1388, 13:07 عصر
Q1 :


SELECT Id , InChargeRole FROM tbl_Processes
WHERE
(PreviousProc = 1)
UNION All
Select Id , InChargeRole FROM tbl_Processes
WHERE ParentId In (SELECT Id FROM tbl_Processes WHERE PreviousProc = 1)

Result :
ID InChargeRole
2 5
3 3
4 1
5 1
5 1
6 1


Q2 :


SELECT Id , InChargeRole FROM tbl_Processes
WHERE
(PreviousProc = 1)
UNION
Select Id , InChargeRole FROM tbl_Processes
WHERE ParentId In (SELECT Id FROM tbl_Processes WHERE PreviousProc = 1)

Result :
ID InChargeRole
2 5
3 3
4 1
5 1
6 1


Q3 :


SELECT Id , InChargeRole FROM tbl_Processes
WHERE
(PreviousProc = 1)
OR
(ParentId In (SELECT Id FROM tbl_Processes WHERE PreviousProc = 1))
OPEN NextProcs

Result :
ID InChargeRole
2 5
3 3
4 1
5 1
6 1


همانطور که میبینید کوئری اول کلا Duplicate رو هم برمیگردونه که مطلوب نیست. در مورد دومی و سومی جواب مشابه میگیریم. اگر دلیل فنی و قانع کننده ای وجود داشته باشه که بگه استفاده از Union بهتره ، من از Union استفاده میکنم. اگرچه هنوز این جواب رو نگرفتم که چطوری از زدن دو کوئری به یک جدول (چه با Subquery و چه با Union ) جلوگیری کنم.

Mahyaa
چهارشنبه 30 اردیبهشت 1388, 13:19 عصر
شما در حقیقت دو جدول دارید ! که با هم ادقام شدند در حالت نرمال سازی نباید یک فیلد از یک جدول با فیلد دیگه ارتباط داشته باشه! (طراحی اشتباه جداول همین روزها آدم رو کلافه می کنه که من چرا باید برای گرفتن اطلاعات از یک جدول یک SubQuery با خود جدول بزنم یا Union کنم )
حالت سون نرمال سازی ( 3nf ) میگه : باید 2nf بوده و صفات خاصه غیرکلید باهم رابطه نداشته باشند ... که در جدول شما این ارتباط وجود داره ( PreviousProc و ParentProc )
(امید وارم حالا با این توضیحات با این موضوع که گفتید کنار بیاین!!
)



شما یک ساختار سلسله مراتبی یا یک ساختار درختی رو چطوری پیاده سازی میکنید. تا جایی که من میدونم برای ساختارهای درختی یک ID وجود داره که کلید اصلیه و یک ParentId هم برای مشخص شده نود پدر وجود داره و این چیزیه که در خیلی از Component ها و Control ها (حداقل اونهایی که من تا به حال باهاش کارکردم)ازش پشتیبانی میکنند.

شما پیشنهاد دیگه ای برای پیاده کردن این دارید ؟

amin_alexi
چهارشنبه 30 اردیبهشت 1388, 15:50 عصر
اگرچه هنوز این جواب رو نگرفتم که چطوری از زدن دو کوئری به یک جدول (چه با Subquery و چه با Union ) جلوگیری کنم.
معلومه اصلا به post های من اصلا توجه نمی کنید !
بازم حرف حرف خودتو میزنی !
من که هر چی دلیل بود گفتم !
ولی انگار شما نمی خوای قانع بشی !
موفق باشی !

Mahyaa
چهارشنبه 30 اردیبهشت 1388, 15:55 عصر
معلومه اصلا به post های من اصلا توجه نمی کنید !
بازم حرف حرف خودتو میزنی !
من که هر چی دلیل بود گفتم !
ولی انگار شما نمی خوای قانع بشی !
موفق باشی !

من روی پاسخهای شما سوالاتی پرسیدم که جوابش رو نگرفتم. دلیل فنی هم اینجا نمیبینم. فقط چیزی که در مورد Self join گفتید به نظر منطقی و درست میاد که دارم امتحانش میکنم.

amin_alexi
چهارشنبه 30 اردیبهشت 1388, 16:22 عصر
شما یک ساختار سلسله مراتبی یا یک ساختار درختی رو چطوری پیاده سازی میکنید. تا جایی که من میدونم برای ساختارهای درختی یک ID وجود داره که کلید اصلیه و یک ParentId هم برای مشخص شده نود پدر وجود داره و این چیزیه که در خیلی از Component ها و Control ها (حداقل اونهایی که من تا به حال باهاش کارکردم)ازش پشتیبانی میکنند.
بله معمولا ما یک View از جداول می سازیم و View رو به اون Component می دیم که اون دوفیلد رو داره !

نگفتم که این روش استفاده از یک جدول غلطه !
اگه درست می خوندی علتی که باید از Join یا uinon یا SubQuery رو نمی دونستی من اون رو توضیح دادم !

من روی پاسخهای شما سوالاتی پرسیدم که جوابش رو نگرفتم.منم چون جواب داده بودم دیگه دلیلی به جواب دادن دوباره ندیدم !

دلیل فنی هم اینجا نمیبینممن حتی اومدم از سطوح نرمال سازی مثال زدم ... دلیل از این فنی تر ! علت Join و Union رو توضیح دادم !
دلیل فنی یعنی چی !؟
بگین ما هم یاد بگیریم !

فقط چیزی که در مورد Self join گفتید به نظر منطقی و درست میاد که دارم امتحانش میکنمتازه به نظر منطقی میاد !
این جور که من فهمیدم من هر چی بگم بی فایدس !
به هر حال موفق باشی !