PDA

View Full Version : مشکل در به دست آوردن جمع مبالغ در دو بازه زمانی متفاوت



kitcat_m18
یک شنبه 03 اسفند 1393, 22:58 عصر
سلام دوستان
من می خوام از یه جدول جمع مبالغ رو از فیلد بستانکار به دست بیارم
در حالت معمولی میشه این:
Select Sum(Bestankar),Code From T_Document Where Month>=1 And Month<=5 Group By Code

تو این دستور جمع بستانکار رو از ماه 1 تا 5 به صورت جداگانه (Group By Code ) به دست میارم
جالا می خوام مثل دستور بالا جمع بستانکار رو از ماه 1 تا 4 به دست بیارم (یک ماه کمتر از بالا)
چطوری می تونم در یک کوئری 2 تا خروجی متفاوت داشته باشم؟

خروجی اولی میشه این


Code
مبلغ بستانکار


111
10000


222
50000


333
3000


444
10000


555
80000




می خوام از دومی این رو بگیرم:


Code
مبلغ بستانکار
مبلغ بستانکار تا ماه قبل


111
10000
9000


222
50000
40000


333
3000
2000


444
10000
5000


555
70000
30000




ممنون :بوس:

kitcat_m18
دوشنبه 04 اسفند 1393, 00:03 صبح
خودم تقریبی یه چیزی نوشتم اما بازم مشکل دارم

SELECT TOP (100) PERCENT T_Document_93.F_CodeIndependent, T_CodeIndependent_93.F_DescIndependent, T_Document_93.F_CodeTotal, T_CodeTotal_93.F_DescTotal, T_CodeTotal_93.F_Mahiyat, T_Document_93.F_CodeDefinite, T_CodeDefinite_93.F_DescDefinite, T_Document_93.F_CodeDetail1, T_CodeDetail1_93.F_DescDetail1, T_Document_93.F_CodeDetail2, T_CodeDetail2_93.F_DescDetail2,
T_Document_93.F_CodeDetail3, T_CodeDetail3_93.F_DescDetail3, T_Document_93.F_CodeDetail4, T_CodeDetail4_93.F_DescDetail4, T_Document_93.F_CodeDetail5, T_CodeDetail5_93.F_DescDetail5,
T_Document_93.F_CodeDetail6, T_CodeDetail6_93.F_DescDetail6, T_Document_93.F_CodeDetail7, T_CodeDetail7_93.F_DescDetail7, T_Document_93.F_DocumentDate, T_Document_93.F_Bed,
(SELECT SUM(F_Bed) AS SumBed
FROM dbo.T_Document_93 AS T_Document_93_1
WHERE (F_Month = T_Document_93.F_Month) AND (ID = T_Document_93.ID)) AS Expr1, T_Document_93.F_Bes AS Sum_Bes,
(SELECT SUM(F_Bes) AS SumBes
FROM dbo.T_Document_93 AS T_Document_93_2
WHERE (F_Month = T_Document_93.F_Month) AND (ID = T_Document_93.ID)) AS Expr2, T_Document_93.F_Kcod, T_Document_93.F_Month
FROM dbo.T_Document_93 AS T_Document_93 LEFT OUTER JOIN
dbo.T_CodeTotal_93 AS T_CodeTotal_93 ON T_Document_93.F_CodeIndependent = T_CodeTotal_93.F_CodeIndependent AND T_Document_93.F_CodeTotal = T_CodeTotal_93.F_CodeTotal LEFT OUTER JOIN
dbo.T_CodeDefinite_93 AS T_CodeDefinite_93 ON T_Document_93.F_CodeIndependent = T_CodeDefinite_93.F_CodeIndependent AND T_Document_93.F_CodeTotal = T_CodeDefinite_93.F_CodeTotal AND
T_Document_93.F_CodeDefinite = T_CodeDefinite_93.F_CodeDefinite LEFT OUTER JOIN
dbo.T_CodeDetail1_93 AS T_CodeDetail1_93 ON T_Document_93.F_CodeIndependent = T_CodeDetail1_93.F_CodeIndependent AND T_Document_93.F_CodeTotal = T_CodeDetail1_93.F_CodeTotal AND
T_Document_93.F_CodeDefinite = T_CodeDetail1_93.F_CodeDefinite AND T_Document_93.F_CodeDetail1 = T_CodeDetail1_93.F_CodeDetail1 LEFT OUTER JOIN
dbo.T_CodeDetail2_93 AS T_CodeDetail2_93 ON T_Document_93.F_CodeIndependent = T_CodeDetail2_93.F_CodeIndependent AND T_Document_93.F_CodeTotal = T_CodeDetail2_93.F_CodeTotal AND
T_Document_93.F_CodeDefinite = T_CodeDetail2_93.F_CodeDefinite AND T_Document_93.F_CodeDetail1 = T_CodeDetail2_93.F_CodeDetail1 AND
T_Document_93.F_CodeDetail2 = T_CodeDetail2_93.F_CodeDetail2 LEFT OUTER JOIN
dbo.T_CodeDetail3_93 AS T_CodeDetail3_93 ON T_Document_93.F_CodeIndependent = T_CodeDetail3_93.F_CodeIndependent AND T_Document_93.F_CodeTotal = T_CodeDetail3_93.F_CodeTotal AND
T_Document_93.F_CodeDefinite = T_CodeDetail3_93.F_CodeDefinite AND T_Document_93.F_CodeDetail1 = T_CodeDetail3_93.F_CodeDetail1 AND
T_Document_93.F_CodeDetail2 = T_CodeDetail3_93.F_CodeDetail2 AND T_Document_93.F_CodeDetail3 = T_CodeDetail3_93.F_CodeDetail3 LEFT OUTER JOIN
dbo.T_CodeDetail4_93 AS T_CodeDetail4_93 ON T_Document_93.F_CodeIndependent = T_CodeDetail4_93.F_CodeIndependent AND T_Document_93.F_CodeTotal = T_CodeDetail4_93.F_CodeTotal AND
T_Document_93.F_CodeDefinite = T_CodeDetail4_93.F_CodeDefinite AND T_Document_93.F_CodeDetail1 = T_CodeDetail4_93.F_CodeDetail1 AND
T_Document_93.F_CodeDetail2 = T_CodeDetail4_93.F_CodeDetail2 AND T_Document_93.F_CodeDetail3 = T_CodeDetail4_93.F_CodeDetail3 AND
T_Document_93.F_CodeDetail4 = T_CodeDetail4_93.F_CodeDetail4 LEFT OUTER JOIN
dbo.T_CodeDetail5_93 AS T_CodeDetail5_93 ON T_Document_93.F_CodeIndependent = T_CodeDetail5_93.F_CodeIndependent AND T_Document_93.F_CodeTotal = T_CodeDetail5_93.F_CodeTotal AND
T_Document_93.F_CodeDefinite = T_CodeDetail5_93.F_CodeDefinite AND T_Document_93.F_CodeDetail1 = T_CodeDetail5_93.F_CodeDetail1 AND
T_Document_93.F_CodeDetail2 = T_CodeDetail5_93.F_CodeDetail2 AND T_Document_93.F_CodeDetail3 = T_CodeDetail5_93.F_CodeDetail3 AND
T_Document_93.F_CodeDetail4 = T_CodeDetail5_93.F_CodeDetail4 AND T_Document_93.F_CodeDetail5 = T_CodeDetail5_93.F_CodeDetail5 LEFT OUTER JOIN
dbo.T_CodeDetail6_93 AS T_CodeDetail6_93 ON T_Document_93.F_CodeIndependent = T_CodeDetail6_93.F_CodeIndependent AND T_Document_93.F_CodeTotal = T_CodeDetail6_93.F_CodeTotal AND
T_Document_93.F_CodeDefinite = T_CodeDetail6_93.F_CodeDefinite AND T_Document_93.F_CodeDetail1 = T_CodeDetail6_93.F_CodeDetail1 AND
T_Document_93.F_CodeDetail2 = T_CodeDetail6_93.F_CodeDetail2 AND T_Document_93.F_CodeDetail3 = T_CodeDetail6_93.F_CodeDetail3 AND
T_Document_93.F_CodeDetail4 = T_CodeDetail6_93.F_CodeDetail4 AND T_Document_93.F_CodeDetail5 = T_CodeDetail6_93.F_CodeDetail5 AND
T_Document_93.F_CodeDetail6 = T_CodeDetail6_93.F_CodeDetail6 LEFT OUTER JOIN
dbo.T_CodeDetail7_93 AS T_CodeDetail7_93 ON T_Document_93.F_CodeIndependent = T_CodeDetail7_93.F_CodeIndependent AND T_Document_93.F_CodeTotal = T_CodeDetail7_93.F_CodeTotal AND
T_Document_93.F_CodeDefinite = T_CodeDetail7_93.F_CodeDefinite AND T_Document_93.F_CodeDetail1 = T_CodeDetail7_93.F_CodeDetail1 AND
T_Document_93.F_CodeDetail2 = T_CodeDetail7_93.F_CodeDetail2 AND T_Document_93.F_CodeDetail3 = T_CodeDetail7_93.F_CodeDetail3 AND
T_Document_93.F_CodeDetail4 = T_CodeDetail7_93.F_CodeDetail4 AND T_Document_93.F_CodeDetail5 = T_CodeDetail7_93.F_CodeDetail5 AND
T_Document_93.F_CodeDetail6 = T_CodeDetail7_93.F_CodeDetail6 AND T_Document_93.F_CodeDetail7 = T_CodeDetail7_93.F_CodeDetail7 LEFT OUTER JOIN
dbo.T_CodeIndependent_93 AS T_CodeIndependent_93 ON T_Document_93.F_CodeIndependent = T_CodeIndependent_93.F_CodeIndependent
WHERE (T_Document_93.F_CodeIndependent = N'01') AND (T_Document_93.F_CodeTotal = N'070') AND (T_Document_93.F_CodeDefinite = N'001')


تو قسمتی که نوشتم F_Month = T_Document_93.F_Month اگه بزنم F_Month < T_Document_93.F_Month هیچ نتیجه ای تو فیلد های ماه Exp1 و Exp2 مقدار Null بر می گردونه که منطقیه
اینجا باید Max(F_Month) رو بگیرم و بعد داخل کوئری ازش استفاده کنم، حالا یکی راهنمایی کنه چجوری ماکزیمم ماه رو بگیرم و اینجا استفاده کنم؟

SabaSabouhi
دوشنبه 04 اسفند 1393, 12:58 عصر
سلام
واقعاً انتظار داری که ما از این حجم script چیزی سر در بیاریم؟
اما در مورد پرسشی که داشتی، بستگی داره چطوری می‌خوای استفاده کنی.
اگه حتماً بخوای با یه Query به دست بیاری، باید Select در Select استفاده کنی.
و اگه نمی‌خوای خیلی پیچیده بشه، تو یه SP دو تا مقدار رو جداگانه به دست بیار
و با یه SELECT تو خروجی قرار بده.
اگه هم تو Application این کار رو انجام می‌دی، اصولاً لزومی نداره که با هم جواب
رو به دست بیاری، به راحتی تک تک محاسبه کن و در کنار هم نمایش بده.

صبا صبوحی

kitcat_m18
دوشنبه 04 اسفند 1393, 13:34 عصر
سلام آقای صبوحی
شما به حجم کد نگاه نکن :بامزه: فقط همون یه خطی رو که گیر کردم رو بتونی بهم بگی عالی میشه
خقیقتش می خوام تو کریستال ریپورت گزارش بگیرم برای همین اگه بتونم تو یه کوئری نتیجه هر دو تا رو داشته باشم واقعا عالی میشه
در غیر اینصورت مجبورم هم وقت زیادی بذارم هم بار زیادی رو دیتابیسم اعمال کنم
گزارشاتمم دیر لود میشن
می تونی یه نمونه برام بذاری؟
ممنون میشم
خودمم تا نیم ساعت دیگه یه دستور ساده تر و دقیق تر از کاری که می خوام انجام بدم میذارم
با تشکر

golbafan
دوشنبه 04 اسفند 1393, 13:39 عصر
سلام خانوم صبوحی
شما به حجم کد نگاه نکن :بامزه: فقط همون یه خطی رو که گیر کردم رو بتونی بهم بگی عالی میشه
خقیقتش می خوام تو کریستال ریپورت گزارش بگیرم برای همین اگه بتونم تو یه کوئری نتیجه هر دو تا رو داشته باشم واقعا عالی میشه
در غیر اینصورت مجبورم هم وقت زیادی بذارم هم بار زیادی رو دیتابیسم اعمال کنم
گزارشاتمم دیر لود میشن
می تونی یه نمونه برام بذاری؟
ممنون میشم
خودمم تا نیم ساعت دیگه یه دستور ساده تر و دقیق تر از کاری که می خوام انجام بدم میذارم
با تشکر

ایشون آقای صبوحی هستند
البته منم این اشتباه رو کردم
فکر کنم همه این اشتباه رو بکنن :چشمک:

در ضمن این همه join سرعت شما رو خیلی کم میکنه ها!!!

SabaSabouhi
دوشنبه 04 اسفند 1393, 14:10 عصر
سلام
دوست عزیز، سعی کن مشکل رو یه کم شفاف‌تر بیان کنی.
همیشه راه حل وجود داره، و هر چی مشکلت رو به‌تر و شفاف‌تر بیان کنی، من و دیگر دوستان
می‌تونیم نظر به‌تری بدیم.
DataSource رو چطوری به کریستال ارسال می‌کنی؟ به صورت DataTable یا List یا مستقیماً خود Query رو میدی؟
من سال‌های زیادی هست که از کریستال استفاده نمی‌کنم.

صبا صبوحی

kitcat_m18
دوشنبه 04 اسفند 1393, 18:34 عصر
سلام دوستان
من مستقیما خود کوئری رو رو در کریستال استفاده می کنم
آقای صبوحی شما الان از چه نرم افزار گزارش گیری ای استفاده می کنین؟
من در پست اول سعی کردم دقیقا بگم چی می خوام اما فکر کنم چون بدون مثال هست نتونستم منظورم رو برسونم
اینم یه نمونه ساده از چیزی که می خوام


SELECT ID, F_Kcod, F_Month, F_Bes,
(SELECT F_Bes FROM dbo.T_Document_93 AS T1 WHERE (F_Month < 2) AND (ID = T_Document_93.ID)) AS Expr1,
F_Bed,
(SELECT F_Bed FROM dbo.T_Document_93 AS T2 WHERE (F_Month < 2) AND (ID = T_Document_93.ID)) AS Expr2
FROM dbo.T_Document_93 AS T_Document_93 WHERE (F_Month <= 2)

تا اینجا مشکلم حل شده و جواب گرفتم
حالا سوال من اینه:
چجوری تو سلکت های داخلی که زدم بفهمم ماکزیمم ماه در سلکت بیرونی چنده؟
یعنی یه همچین چیزی می خوام:

SELECT ID, F_Kcod, F_Month, F_Bes, (SELECT F_Bes FROM dbo.T_Document_93 AS T1 WHERE (F_Month < Max(T_Document_93.F_Month)) AND (ID = T_Document_93.ID)) AS Expr1,
F_Bed,
(SELECT F_Bed FROM dbo.T_Document_93 AS T2 WHERE (F_Month < Max(T_Document_93.F_Month)) AND (ID = T_Document_93.ID)) AS Expr2
FROM dbo.T_Document_93 AS T_Document_93 WHERE (F_Month <= 2)

من تو کدی گکه زدم وقتی می گم Max(T_Document_93.F_Month) میره ماکزیمم همون ردیف رو پیدا می کنه اما من می خوام بهش بگم کوچکتر از ماکزیمم کل سلکت بیرونی

ممنون میشم راهنمایی کنید :لبخندساده:

golbafan
دوشنبه 04 اسفند 1393, 18:39 عصر
اول جدول مربوط به سلکت داخلی ایجاد میشه بعد بیرونی
پس با داخلی نمیشه بیرونی رو چک کنید...

kitcat_m18
دوشنبه 04 اسفند 1393, 18:42 عصر
وقتی دستی ماه رو به کوئری میدم درست کار می کنه
اینم یه نمونه از خروجی:128795

kitcat_m18
دوشنبه 04 اسفند 1393, 18:45 عصر
سلام golbafan گرامی
به قول آقای صبوحی همیشه راه حل وجود داره دوست عزیز :لبخندساده:
اگه بشه اول ماکزیمم رو بگیریم و بعد از این کوئری استفاده کنیم که عالی میشه
بازم ممنون که مشارکت داشتین

SabaSabouhi
دوشنبه 04 اسفند 1393, 19:48 عصر
سلام دوستان
من مستقیما خود کوئری رو رو در کریستال استفاده می کنم
آقای صبوحی شما الان از چه نرم افزار گزارش گیری ای استفاده می کنین؟
من در پست اول سعی کردم دقیقا بگم چی می خوام اما فکر کنم چون بدون مثال هست نتونستم منظورم رو برسونم
اینم یه نمونه ساده از چیزی که می خوام


SELECT ID, F_Kcod, F_Month, F_Bes,
(SELECT F_Bes FROM dbo.T_Document_93 AS T1 WHERE (F_Month < 2) AND (ID = T_Document_93.ID)) AS Expr1,
F_Bed,
(SELECT F_Bed FROM dbo.T_Document_93 AS T2 WHERE (F_Month < 2) AND (ID = T_Document_93.ID)) AS Expr2
FROM dbo.T_Document_93 AS T_Document_93 WHERE (F_Month <= 2)

تا اینجا مشکلم حل شده و جواب گرفتم
حالا سوال من اینه:
چجوری تو سلکت های داخلی که زدم بفهمم ماکزیمم ماه در سلکت بیرونی چنده؟
یعنی یه همچین چیزی می خوام:

SELECT ID, F_Kcod, F_Month, F_Bes, (SELECT F_Bes FROM dbo.T_Document_93 AS T1 WHERE (F_Month < Max(T_Document_93.F_Month)) AND (ID = T_Document_93.ID)) AS Expr1,
F_Bed,
(SELECT F_Bed FROM dbo.T_Document_93 AS T2 WHERE (F_Month < Max(T_Document_93.F_Month)) AND (ID = T_Document_93.ID)) AS Expr2
FROM dbo.T_Document_93 AS T_Document_93 WHERE (F_Month <= 2)

من تو کدی گکه زدم وقتی می گم Max(T_Document_93.F_Month) میره ماکزیمم همون ردیف رو پیدا می کنه اما من می خوام بهش بگم کوچکتر از ماکزیمم کل سلکت بیرونی

ممنون میشم راهنمایی کنید :لبخندساده:

سلام
1. من یه مدتی از ActiveReport مربوط به شرکت DataDynamics استفاده می‌کردم. الان هم که از کامپوننت‌های DevExpress استفاده می‌کنم از ابزارهای اون استفاده می‌کنم.
راستش از نظر من هر چی ابزار گزارش‌سازی ساده‌تر و سبک‌تر باشه بهتره. چون بقیه‌ی کارهاش رو خودم انجام می‌دم.
2. من انتظار داشتم تو مثلا شما Group by یا Max ببینم که ندیدم. ( صورت مساله‌ی این تصور رو برای من ایجاد کرده بود )
اونطوری که من فهمیدم، شما یه Select اصلی داری، که می‌خوای یه جوری با پارامتر یا روش دیگه عدد ماه رو بهش بدی ( همین که الان تو مثال شما 2 هست )
و می‌خوای به صورت خودکار تو دو تا Select دیگه هم همون اعمال بشه. درسته؟
شما تو SELECT اصلی جدول dbo.T_Document_93 رو بهش نام مستعار ( Alias ) دادی که همون T_Document_93 هست.
خوب این کارت اشتباه هست. چون این دو عبارت دقیقاً یکی هستن. در واقع وقتی شما Schema رو ندی همون dbo فرض می‌کنه.
به جدولت تو Select اصلی یه اسم دیگه بده. مثلاً T3. در این صورت Selectهای بالایی مقدار رو می‌شناسن.
ولی باز هم فکر کنم تو Selectهای داخلی اشتباه داری، چون به نظر میاد باید از Max استفاده کنی.

صبا صبوحی

kitcat_m18
دوشنبه 04 اسفند 1393, 23:39 عصر
سلام
1. من یه مدتی از ActiveReport مربوط به شرکت DataDynamics استفاده می‌کردم. الان هم که از کامپوننت‌های DevExpress استفاده می‌کنم از ابزارهای اون استفاده می‌کنم.
راستش از نظر من هر چی ابزار گزارش‌سازی ساده‌تر و سبک‌تر باشه بهتره. چون بقیه‌ی کارهاش رو خودم انجام می‌دم.
2. من انتظار داشتم تو مثلا شما Group by یا Max ببینم که ندیدم. ( صورت مساله‌ی این تصور رو برای من ایجاد کرده بود )
اونطوری که من فهمیدم، شما یه Select اصلی داری، که می‌خوای یه جوری با پارامتر یا روش دیگه عدد ماه رو بهش بدی ( همین که الان تو مثال شما 2 هست )
و می‌خوای به صورت خودکار تو دو تا Select دیگه هم همون اعمال بشه. درسته؟
شما تو SELECT اصلی جدول dbo.T_Document_93 رو بهش نام مستعار ( Alias ) دادی که همون T_Document_93 هست.
خوب این کارت اشتباه هست. چون این دو عبارت دقیقاً یکی هستن. در واقع وقتی شما Schema رو ندی همون dbo فرض می‌کنه.
به جدولت تو Select اصلی یه اسم دیگه بده. مثلاً T3. در این صورت Selectهای بالایی مقدار رو می‌شناسن.
ولی باز هم فکر کنم تو Selectهای داخلی اشتباه داری، چون به نظر میاد باید از Max استفاده کنی.

صبا صبوحی


سلام مهندس،
منم با اکتیو ریپورت خیلی کار کردم، اما چون زبان برنامه نویسی من VB6 هست و اکتیو ریپورتی که رو VB6 کار می کنه راست به چپ رو ساپورت نمی کرد گذاشتمش کنار
البته کریستال ریپورت هم تو ویندوز XP با راست به چپ کردن مخصوصا واسه تاریخ ها مشکلاتی رو داره اما بهتر از هیچیه

خدمتت عارضم که Group By رو داخل خود کریستال با ایجاد Group Header و Footer انجام میدم (عکسشم میذارم ملاحظه بفرمایید)
در رابطه با نام مستعار حق با شماست اما مشکلی هم ایجاد نمی کنه
در رابطه با MAX منم الان دنبال همین هستم که چجوری MAX سلکت بیرونی رو پیدا کنم و در داخلی ها استفاده کنم

http://s4.picofile.com/file/8173004226/untitled.JPG

SabaSabouhi
سه شنبه 05 اسفند 1393, 08:26 صبح
سلام مهندس،
منم با اکتیو ریپورت خیلی کار کردم، اما چون زبان برنامه نویسی من VB6 هست و اکتیو ریپورتی که رو VB6 کار می کنه راست به چپ رو ساپورت نمی کرد گذاشتمش کنار
البته کریستال ریپورت هم تو ویندوز XP با راست به چپ کردن مخصوصا واسه تاریخ ها مشکلاتی رو داره اما بهتر از هیچیه

خدمتت عارضم که Group By رو داخل خود کریستال با ایجاد Group Header و Footer انجام میدم (عکسشم میذارم ملاحظه بفرمایید)
در رابطه با نام مستعار حق با شماست اما مشکلی هم ایجاد نمی کنه
در رابطه با MAX منم الان دنبال همین هستم که چجوری MAX سلکت بیرونی رو پیدا کنم و در داخلی ها استفاده کنم



سلام
چند تا نکته بهت بگم.
1. وقتی یه Select تو قسمت select-list می‌گذاری حتماً باید فقط یک مقدار برگردونه، پس اونجا یا باید از Max استفاده کنی یا از GroupBy به همراه Max
2. نام مستعار وقتی معنی داره که با نام واقعی فرق کنه. dbo.T_Document_93 با T_Document_93 هیچ فرقی نداره و تو Selectهای داخلی مشکل‌ساز می‌شه
3. نتیجه‌ی هر Select یک جدول هست، که می‌تونی به عنوان یک منبع تو Select ازش استفاده کنی.


SELECT A.Col1, A.Col2
, ColX1 = ( SELECT Sum( Col3 ) FROM MyTable WHERE Date < M.MaxDate )
, ColX2 = ( SELECT Top 1 Col3 FROM MyTable WHERE Date < M.MaxDate )
FROM ( SELECT MaxDate = Max( DateColumn ) FROM MyTable WHERE MyCondition ) M
JOIN MyTable A ON A.Date <= M.MaxDate


من این Script فرضی رو نوشتم که بتونی ازش ایده بگیری، گمان کنم کارت رو راه بندازه.



صبا صبوحی

kitcat_m18
چهارشنبه 06 اسفند 1393, 14:57 عصر
سلام دوست عزیز
ممنون از کوئری
دقیقا همینو می خواستم :قلب:
البته یه چیزایی رو تغییر دادم بازم ممنون