PDA

View Full Version : مهم : (سرعت) ایجاد گزارش دفترکل با یک Query



shsoft
یک شنبه 25 اردیبهشت 1384, 20:25 عصر
با سلام
همان طور که می دونید سرعت عمل در نمایش گزارش ها بسیار مهمه.

حالا مشکل رو با یک مثال توضیح می دم:
- دو جدول داریم که شامل دریافت و پرداخت می شود.
- در هر جدول 10,000رکورد برای هر کد حساب وجود دارد که در مجموع 200 کد حساب دارم

Table1= 10,000 * 200=>2,000,000 Records
Table2= 10,000 * 200=>2,000,000 Records


خوب حال اگه بخواهیم یک Query بنویسیم که در کمترین زمان ممکن گزارش رو تهیه کنه باید چکار کنیم
لطفا نظرات خودتون رو بنویسید
:flower:

AminSobati
یک شنبه 25 اردیبهشت 1384, 23:40 عصر
دوست عزیزم،
شما میبایست اول دقیقا Query مورد نیاز رو بنویسین، بعد متناسب با اون Indexها ساخته بشن.

shsoft
دوشنبه 26 اردیبهشت 1384, 10:12 صبح
اگه میشه در مورد این بخش از کار صحبت کنیم

ما یک جدول داریم که یه صورت زیر حاوی اطلاعات حساب است که حاصل یک Query می باشد
Treport.id
Treport.date
treport.debtor
treport.credito
debtor شامل بدهکار و creditor شامل بستانکار است
حالا چگونه می شود با یک query مقادیر ستون مانده را بدست آورد

AminSobati
دوشنبه 26 اردیبهشت 1384, 12:08 عصر
بدهکار منظورتون حاصل تفریق Debtor و Creditor هستش؟ یا...

shsoft
دوشنبه 26 اردیبهشت 1384, 17:43 عصر
debtor شامل بدهکار - یعنی شامل مقداری است که دارای ارزش منفی می باشد
creditor شامل بستانکار است - یعنی شامل مقدار مثبت است.

در واقع این دو فیلد همان ستون های دفترکل هستند

AminSobati
دوشنبه 26 اردیبهشت 1384, 22:57 عصر
ببخشید که من سوالم رو بد مطرح کردم. منظورم تعریف ستون مانده بود
اگر میبایست تفریق بشن که به این صورت عمل کنین:
SELECT Creditor-Debtor FROM MyTable

shsoft
سه شنبه 27 اردیبهشت 1384, 00:08 صبح
آقا ببخشید وقت شما رو خیلی گرفتیم
گزارشی رو که من می خوام دقیقا گزارش دفترکل است که در زیر چند خط از اون رو مثال می زنم

ردیف / تاریخ / شرح / بدهکار / بستانکار / مانده

1 /25/2/84 / بابت خرید کالا / 10000 / 0 / 10000-
2 /25/2/84 / پرداخت نقدی / 0 / 10000 / 0
3 /26/2/84 / بابت اعتبار حساب / 0 / 200000 / 200000+

خوب همون طور که می دونید ستون مانده نمایان گر وضعیت حساب تا آن سطر است
مثلا در سطر اول -10000 بدهکار شده است پس مانده برابر -10000 است
در سطر دوم 10000 بستانکار شده است خوب حالا مقدار مانده سطر دوم برابر مقدار مانده سطر اول می شود با مقدار بستانکار سطر دوم

دستوری که شما نوشتین برای گام اول کاملا درسته و در مثال بالا دارای خروجی زیر است:

-10000
10000
200000
خوب حالا اگر بشه دستوری نوشت که هر سط رو با سطر قبلیش جمع کنه مشکل حله
یعنی منظورم همان سطر های ستون مانده است:
ردیف
1 0+-10000=-10000
2 -10000+10000=0
3 0 + 200000=200000
همان طور که مشاهده می کنید به روش بالا مقدار ستون مانده بدست آمد
آقا شرمنده که طولانی شد :oops:

AminSobati
شنبه 31 اردیبهشت 1384, 10:57 صبح
پس برای مثال، اول من تابع رو میسازم:

create function dbo.Calc(@Radif int, @Bedehkar money, @Bestankar money)
returns money
as
begin
declare @PrevRecord as int
declare @RetVal money
select @PrevRecord=max(radif) from dbo.test where radif<@radif
if @PrevRecord is null
begin
set @RetVal=@Bestankar-@Bedehkar
end
else
begin
declare @PrevMandeh money
select @PrevMandeh=Mandeh from dbo.test where radif=@PrevRecord
set @RetVal=@Bestankar-@Bedehkar+@PrevMandeh
end
return @RetVal
end

بعد جدول رو (باز برای مثال):

create table test(
Radif int,
Bedehkar money,
Bestankar money,
Mandeh as dbo.Calc(Radif, Bedehkar, Bestankar))


insert test values(1, 1000,0)
insert test values(2, 0,1000)
insert test values(3, 0, 2000)

و برای بهینه کردن سرعت تابع، این ایندکس رو نیاز داریم:

create index ix1 on test(radif)
حالا نتیجه:

select * from test
فقط در مورد فیلد Radif دقت کنید که ممکنه ردیف رو شما به شکل دیگه ای کنترل کرده باشین. در صورت نیاز، تابع رو ویرایش کنین تا با ساختار جدول شما مطابقت داشته باشه.
موفق باشید

shsoft
شنبه 31 اردیبهشت 1384, 12:54 عصر
با سلام
از اینکه این همه وقت گذاشتین متشکرم :flower:

bahman.net
چهارشنبه 10 اسفند 1384, 01:53 صبح
سلام بر همگی
این تابع درخط 7 وبه شرط where radif<@radif
و علامت(; )خطا میده کسی میتونه بگه خطاش چیه؟ یا علت اون چیه
خیلی ممنون می شم

bahman.net
چهارشنبه 10 اسفند 1384, 01:53 صبح
کسی جواب ما رو نمی خواد بده؟؟؟؟؟؟؟!!!!!

AminSobati
چهارشنبه 10 اسفند 1384, 11:16 صبح
به جای < علامت کوچکتر قرار بدین. اینجا علامت کوچکتر تبدیل به کدهای HTML شده!

bahman.net
پنج شنبه 18 اسفند 1384, 01:52 صبح
جناب ثباتی خیلی ازتون ممنونم

حمیدرضاصادقیان
دوشنبه 17 اردیبهشت 1386, 17:18 عصر
سلام.ببخشید این تاپیک خیلی قدیمی رو بالا اوردم.اخه با اجرای اون روی تعداد رکوردهای بالای 40 یا 50 ردیف پیغام خطا میدهد که بیشترین مقدار برای nesting level 32 می باشد.

AminSobati
دوشنبه 17 اردیبهشت 1386, 22:37 عصر
دقیقا چه کاری انجام میدین که این پیغام رو میده؟

حمیدرضاصادقیان
دوشنبه 17 اردیبهشت 1386, 23:42 عصر
تمام مراحلی که خودتون گفتین رو انجام بدین فقط به جای 3 رکورد 50 رکورد ثبت کنین با این مشکل مواجه میشین

AminSobati
سه شنبه 18 اردیبهشت 1386, 01:29 صبح
من همون 3 رکورد رو به تعداد دفعات بیشتر Insert کردم (نزدیک به 200 رکورد) و بعد Select زدم به کمک تابع Calc ولی مشکلی نداشتم. مطمئن هستین که تابع Calc رو در جای دیگه Call نکردین؟ چون مشکل Nest شدن تا 32 مرحله که برای توابع، Trigger یا SP ها رخ میده فقط در صورت تو در تو شدن پیش میاد

حمیدرضاصادقیان
سه شنبه 18 اردیبهشت 1386, 08:36 صبح
در حقیقت من ابتدا تابع رو ایجاد کردم طبق فرمایش شما. بعد جدول رو ساختم و در فرمول جدول همان فیلد مانده ، این تابع رو صدا زدم. بعد هم یک select از جدول گرفتم تا 30 رکورد تست کردم مشکلی نداشت. ولی بالای 30 رکورد به مشکل بر می خورد.

حمیدرضاصادقیان
سه شنبه 18 اردیبهشت 1386, 10:35 صبح
استاد من اول که تعداد زیادی ردیف وارد کردم در هر دو ستون بد و بس عدد وارد کردم. فکر کردم شاید ایراد از این باشه. شروع کردم از اول در جدول رکورد اضافه کردم تا 35 ردیف درست انجام شد.
دقیقا به 36 که رسید خطا داد.

حمیدرضاصادقیان
سه شنبه 18 اردیبهشت 1386, 23:09 عصر
استاد ثباتی بررسی نکردین شرایط رو؟؟ اگر امکان داره از دیتابیس خودتون یا از اون جدول یک backup قرار بدین تا شاید من اشتباه میکنم

AminSobati
چهارشنبه 19 اردیبهشت 1386, 00:43 صبح
حمید جان حق با شماست، اشکال کار رو پیدا کردم. این Query بدون تابع رو شما هم تست کن، امیدوارم جواب بده:


select radif,Bedehkar, Bestankar,
(select sum(-1*Bedehkar+Bestankar) from test t2 where radif<=test.radif)
from test

linux
چهارشنبه 19 اردیبهشت 1386, 02:22 صبح
اگه میشه در مورد این بخش از کار صحبت کنیم

ما یک جدول داریم که یه صورت زیر حاوی اطلاعات حساب است که حاصل یک Query می باشد
Treport.id
Treport.date
treport.debtor
treport.credito
debtor شامل بدهکار و creditor شامل بستانکار است
حالا چگونه می شود با یک query مقادیر ستون مانده را بدست آورد
قبلا عین همین سوال را مطرح کردم جوابی را که گرفتم و الان هم خوب کار می کند
می توانید سوال و جواب ها را اینجا ببنید
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=79764

حمیدرضاصادقیان
چهارشنبه 19 اردیبهشت 1386, 08:39 صبح
استاد ممنون این جواب داد.حالا اون -1 چیست که شما ضرب کردین؟

AminSobati
چهارشنبه 19 اردیبهشت 1386, 10:24 صبح
استاد ممنون این جواب داد.حالا اون -1 چیست که شما ضرب کردین؟
برای اینکه فیلد بدهکار باعث بشه از مجموع کل تفریق انجام بده. البته اگر Bestankar و Bedehkar تفریق بشن همون نتیجه رو باید بده

AminSobati
چهارشنبه 19 اردیبهشت 1386, 10:25 صبح
قبلا عین همین سوال را مطرح کردم جوابی را که گرفتم و الان هم خوب کار می کند
می توانید سوال و جواب ها را اینجا ببنید
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=79764

هر دو یک روش هستن!

حمیدرضاصادقیان
چهارشنبه 19 اردیبهشت 1386, 13:00 عصر
ببخشید استاد من نتونستم این روش رو روی جدول خودم پیاده سازی کنم. یک راهنمایی میخواستم.
ببینید ساختار جدول من به این صورته که من در جدول سند ترکیب ردیف و شماره سند رو کلید اصلی گرفتم زیرا برای هر سند حداقل دو ردیف وجود داره که شماره سندش تکرار میشه به همین خاطر این کارو کردم.
بعد یک فیلد دارم که اگر 0 بود یعنی بستانکار و اگر 1 بود یعنی بدهکار.
و یک ستون مبلغ دارم. یعنی برای بدهکار و بستانکار یک ستون مجزا قرار ندادم.
حالا با این وضعیت چیکار باید بکنم.؟

AminSobati
چهارشنبه 19 اردیبهشت 1386, 13:54 عصر
لطفا Script و نمونه Data پست کنین

حمیدرضاصادقیان
چهارشنبه 19 اردیبهشت 1386, 14:30 عصر
استاد اینم نمونه دیتابیسش.

AminSobati
چهارشنبه 19 اردیبهشت 1386, 22:14 عصر
فکر میکنم Case راه حل خوبی باشه. اگر type مثلا بدهکار بود، فیلد مربوطه منفی بشه و در جمع شرکت کنه، اگر بستانکار بود که روال عادی

حمیدرضاصادقیان
پنج شنبه 20 اردیبهشت 1386, 09:22 صبح
اخه استاد من از case استفاده کردم ولی وقتی فیلدهاشو در جمع شرکت میدهم میگه این فیلدها وجود نداره.

AminSobati
پنج شنبه 20 اردیبهشت 1386, 14:21 عصر
لابد از Alias فیلدها توی محاسبات استفاده کردین!

linux
پنج شنبه 20 اردیبهشت 1386, 20:26 عصر
هر دو یک روش هستن!
بله هر دو یکی هستند گفتم لینک مطلب تو سایت باشه چون آنجا کاملا از اول تا اخر با توضیحات کامل مساله حل شده

حمیدرضاصادقیان
جمعه 21 اردیبهشت 1386, 10:10 صبح
استاد میشه یک نمونه مثال بزنید من که دیگه هنگ کردم و اینجوری شمارو اذیت میکنم.

علامت سوال
سه شنبه 02 مرداد 1386, 12:05 عصر
پس برای مثال، اول من تابع رو میسازم:

create function dbo.Calc(@Radif int, @Bedehkar money, @Bestankar money)
returns money
as
begin
declare @PrevRecord as int
declare @RetVal money
select @PrevRecord=max(radif) from dbo.test where radif&lt;@radif
if @PrevRecord is null
begin
set @RetVal=@Bestankar-@Bedehkar
end
else
begin
declare @PrevMandeh money
select @PrevMandeh=Mandeh from dbo.test where radif=@PrevRecord
set @RetVal=@Bestankar-@Bedehkar+@PrevMandeh
end
return @RetVal
end

بعد جدول رو (باز برای مثال):

create table test(
Radif int,
Bedehkar money,
Bestankar money,
Mandeh as dbo.Calc(Radif, Bedehkar, Bestankar))


insert test values(1, 1000,0)
insert test values(2, 0,1000)
insert test values(3, 0, 2000)

و برای بهینه کردن سرعت تابع، این ایندکس رو نیاز داریم:

create index ix1 on test(radif)
حالا نتیجه:

select * from test
فقط در مورد فیلد Radif دقت کنید که ممکنه ردیف رو شما به شکل دیگه ای کنترل کرده باشین. در صورت نیاز، تابع رو ویرایش کنین تا با ساختار جدول شما مطابقت داشته باشه.
موفق باشید
آقای امین ثباتی راه حل بسیار جالبه در صورتی که فیلد ردیف رو نداشته باشیم و بخایم بجای اون از فیلد AutoNumber استفاده کنیم یا فیلدی از تنوع Uniqueidentifier تکلیف چی میشه؟
با تشکر قبلی از استاد گرامی

danial82
شنبه 06 بهمن 1386, 15:43 عصر
من موجودی همه مشتریان و باهم تو یه جدول میریزم و با فیلد member_id از هم جداشون میکنم یعنی موجودی هرکی رو بدست میارم حالا با این تفاسیر تابع چه تغییری میکنه و اینکه الان جدولم پر از داده است

farzad1
چهارشنبه 20 آذر 1387, 14:24 عصر
با سلام خدمت همه
من هم مشکل شما رو دارم حال اگر جدول من ستون ديگري به نام کد معين داشت (Code) که چندين حساب توي همين جدول باشند چطوري مي تونم باقيمانده اونها رو از هم جداگانه حساب کنم. تازه سال مالي رو هم حساب كنيد كه فيلد Date هم داشته باشه.
با تشکر