PDA

View Full Version : استفاده بهینه چندبار از یک سلکت



bebakhsh
شنبه 24 مرداد 1394, 12:13 عصر
سلام

من یه سلکتی دارم که عملیات زیادی رو انجام میده و یه سری داده رو بر می گردونه. فرض کنید که یکی از فیلدهایی که بر می گردونه ID هست
حالا نیاز دارم که یه سلکت دیگه بنویسیم که یه سری فیلدی رو بر می گردونه. فرض کنید یکی از این فیلدها که بر می گردونه ParentID هستش که این ParentID معادل همون ID در سلکت اول می باشد

حالا نکته اینجاست که من از سلکت دوم رکوردهایی رو میخام که بیاره که ParentID <> ID

نمیخام ID سلکت های اولی رو تو یه تیبل مجازی اینسرت کنم چون پرفرمنس رو پایین میاره
اومدم از دستورات cte استفاده کردم . به شکل زیر
withFirstSelectas)
...(

select

IDfromFirstSelect

Union

select
ParentID

from

SecondSelect

left

joinFirstSelectonFirstSelect.ID=ParentID

where

FirstSelect.IDisnotnull


مشکلی که پیش میاد اینه که میاد دو بار دستور with رو انجام میده و زمان انجام روال من دو برابر میشه
اگه بخام تابع هم بنویسیم دقیقا همین مشکل رو داره
به نظر دوستان راهی هست که بخام یه کد رو دو بار استفاده کنم ولی دو بار اجرا نشه مثه دستور اینسرت

bebakhsh
شنبه 24 مرداد 1394, 13:34 عصر
سلام

من یه سلکتی دارم که عملیات زیادی رو انجام میده و یه سری داده رو بر می گردونه. فرض کنید که یکی از فیلدهایی که بر می گردونه ID هست
حالا نیاز دارم که یه سلکت دیگه بنویسیم که یه سری فیلدی رو بر می گردونه. فرض کنید یکی از این فیلدها که بر می گردونه ParentID هستش که این ParentID معادل همون ID در سلکت اول می باشد

حالا نکته اینجاست که من از سلکت دوم رکوردهایی رو میخام که بیاره که ParentID <> ID

نمیخام ID سلکت های اولی رو تو یه تیبل مجازی اینسرت کنم چون پرفرمنس رو پایین میاره
اومدم از دستورات cte استفاده کردم . به شکل زیر
withFirstSelectas)
...(

select

IDfromFirstSelect

Union

select
ParentID

from

SecondSelect

left

joinFirstSelectonFirstSelect.ID=ParentID

where

FirstSelect.IDisnotnull


مشکلی که پیش میاد اینه که میاد دو بار دستور with رو انجام میده و زمان انجام روال من دو برابر میشه
اگه بخام تابع هم بنویسیم دقیقا همین مشکل رو داره
به نظر دوستان راهی هست که بخام یه کد رو دو بار استفاده کنم ولی دو بار اجرا نشه مثه دستور اینسرت


کسی نیست جواب بده؟
عجله دارم دوستان

tooraj_azizi_1035
شنبه 24 مرداد 1394, 14:18 عصر
سلام
اگه میشه یک نمونه خروجی بذارین.

bebakhsh
یک شنبه 25 مرداد 1394, 07:30 صبح
سلام
اگه میشه یک نمونه خروجی بذارین.



سلام منظورتون از خروجی، نتیجه اجرای کوئری هست؟ اگه منظور شما این هست که خدمتتون عرض کنم نتیجه رو درست برمیگردونه اما در ظاهرا دستور with رو چون دوبار استفاده کردم بنابراین دوبار میاد دستور with رو اجرا میکنه و زمان اجرای کوئری من دو برابر میشه . من به دنبال راهی هستم که این زمان رو به حداقل برسونم

چون کوئری من خیلی زیاده اینجا قرارش ندادم ولی اگه خواستید یه نگاهی بیندازید من پیوستش میکنم

bebakhsh
یک شنبه 25 مرداد 1394, 13:19 عصر
اجازه بدین من به طور کامل توضیح بدم
این روال یه گزارش دو سطحی هست . با سطح یک که مشکلی ندارم . مشکل رو سطح دو هست هنگامی که میخام گزارش رو بر اساس تاریخ فیلتر کنم. فرض کنید که من تو یه بازه زمانی مشخص شده میخام گزارش بگیرم. رکوردهایی که میخام تو این بازه فیلتر بشن رو میاره. علاوه بر این ها باید یه رکورد دیگه هم بیاره که در واقع منقول از قبل تاریخ فیلتر شده است. مشکل سر رکورد منقول هست.
توضیح بیشتر این که مثلا من میخام گزارش مالی افراد رو تو بازه تاریخی 930505 تا 940101 بگیرم. خب این که کاری نداره . ولی میخام یه رکورد دیگه هم بیارم که گزارش مالی هر فرد رو از ابتدای سال مالی تا تاریخ 030505 به صورت یه رکورد بیاره (رکورد به این صورت هست که میاد گردش مالی فرد رو از اول سال تا تاریخ 930505 جمع میکنه و تو یه رکورد نشون میده) حالا مشکل من سر محاسبه این رکورد هم نیست و اونو هم حساب میکنم. مشکل اینجاست که مثلا آقای x تو بازه تاریخی 930505 تا 940101 هیچ گردش مالی نداره ولی قبل از 930505 گردش مالی داره و تو گزارش من نباید آقای x بیاد چون تو فیلتر تاریخ من نیست.

حالا

کاری که من کردم اینه :

یه WITH نوشتم که همه رکوردها رو تو بازه تعریف شده میده . حالا از اون WITH سلکت کردم و با سلکتی که منقول از قبل هست یونیون میکنم به شرطی که حتما آی دی سلکت دومی تو اولی هم اومده باشه. یعنی چی؟ یعنی اینکه حتما همه افرادی بیان که تو بازه تعریف شده من قرار دارن

این نکته رو هم عرض کنم که کوئری درسته و کاملا جواب میده و هزینه زمانی بدی هم نداره ولی چون داره دستور WITH رو دو بار اجرا می کنه ، بنابراین زمان کوئری من هم دو برابر میشه. میخاستم ببینم راهی به جز استفاده از WITH هست ؟ البته نمیخام از اینسرت تو تیبل مجازی هم استفاده کنم چون اینسرت هم پرفرمنس رو پایین میده با توجه به اینکه داده هام زیاده

ممنون

tooraj_azizi_1035
یک شنبه 25 مرداد 1394, 14:05 عصر
فرض کنید یک cte داریم که میاد اطلاعات مالی افراد از ابتدای سال تا
930505 رو نشون میده و Cte دومی هم داریم که اطلاعات مالی رو از 930505 تا 940101 نشون میده تا ایجا محاسبه گردش مالی انجام نشده.
اگه این دو cte رو براساس ID فرد JOIN کنیم در این صورت افردای که در هر دو بازه هستن نشون داده میشن بعد بیایم محاسبه گردش مالی رو روی نتیجه join انجام بدیم.

bebakhsh
دوشنبه 26 مرداد 1394, 07:39 صبح
این چیزی که شما فرمودید کار منو راه نمیاندازه.
چیزی که من میخام خروجی من باشه : یه رکوردمنقول + رکوردهای فیلتر شده با توجه به بازه زمانی. و این مستلزم این هست که من دوتا سلکت رو حتما با هم یونیون کنم
اما پیشنهادی که شما دادین که جوین بزنم ، خروجیدرستی به من نمیده. چون طبق گفته شما (cteداریم که میاد اطلاعات مالی افراد از ابتدای سال 930505 رو نشون میده و Cte دومی هم داریم که اطلاعات مالی رو از 930505تا 940101 نشون میده تا ایجا محاسبه گردش مالی انجام نشده اگه این دو cte رو براساس ID فرد JOINکنیم در این صورت افردای که در هر دو بازه هستن نشون داده میشن ) کاملا درستهافرادی که در هر دو بازه هستند رو نشون میده اما مشکل سر بعد قضیه هست (بعد بیایممحاسبه گردش مالی رو روی نتیجه joinانجام بدیم)
تا اینجا فقط من افراد مشترک تو هر دو سلکترو پیدا کردم .. پس حالا باید سلکت اول رو بزنم و جوین کنم با ریزالت بالا ودوباره سلکت دوم رو بزنم و جوین کنم با ریزالت بالا.
در واقع هر سلکتی داره دو بار اجرا میشه. (دقتکنید که سلکت اول و دوم با هم فرق دارن)
در واقع شما هم دارین سلکت ها رو تکرارمیکنید فقط من با دستور سی تی ای و شما با جوین

bebakhsh
دوشنبه 26 مرداد 1394, 13:04 عصر
کسی نیست جواب بده؟