PDA

View Full Version : اضافه کردن مبلغ ثابت به تمام ردیف های یه جدول



mtzstar
یک شنبه 03 شهریور 1392, 16:13 عصر
با عرض سلام و خسته نباشی خدمت دوستان عزیز
دوستان بنده با یه مشکل روبه رو شدم کلی سرچ زدم ولی متاسفانه به جوابه درستی نرسیدم
یه سناریو رو در نظر بگیرد که
ما برای هر نفر یه صندوق داریم که مقدار پولی که واریز می کنند مشخصه و این پول به حساب همون شخص میرود
حالا فرض کنید ما x نفر داریم که هر کدام داری حساب خود هستند که شامل دو فیلد بدهکاری و بستانکاری باشد
و بعد می خواهیم خرجی انجام بدیم که بین این اشخاص پول به صورت مساوی تقسیم شود و به حساب بدهکاری اضاف یا از حساب بستانکاری کسر شود (توجه داشته باشید برای یک نفر به راحتی امکان پذیر هست)اما اگر ما x نفر داشته باشیم که هرکدام y حساب رو داشته باشه
باید بیایم که ابتدا حساب بدهکاری و بستانکاری هر فرد رو با استفاده از دیتا ریدر چک کنیم و اون رو تو متغییر ذخیره کنیم و بعد اون مبلغ ثابت رو به حساب بدهکاری اضاف یا از حساب بستانکاری شخص کسر کنیم و این روند تا آخرین نفر برای هر شخص ادامه دارد
مشکل بنده اینجاست که میدونم با یا حلقه foreach باید پیاده سازی کنم تا تمام حساب ها رو چک کنم و اون مبلغ ثابت رو از حساب هر شخص کم کنم
ولی نمی دونم که چطوری باید پیاده سازی بشه
مراحلی که مدنظر من هستش اینه
1)اول دیتا ریدر حساب هر شخص رو بخونه (بدهکاری یا بستکاری)
2)مبلغ ثابت تقسیم شده از قبل رو از حساب شخص کسر کنه
3)و به ردیف بعد برود و این مراحل 1و 2 را برای بقیه انجام بده الی آخرین نفر

ممنون میشم اگه دوستان بتونن در قالبه یه مثال یا پروژه ای اگه وجود داره یا کد نوشته شده به بنده کمک کن
ا تشکر فراوان

mousa1992
یک شنبه 03 شهریور 1392, 19:10 عصر
چرا این همه دردسر
همش با ی دستور UPDATE قابل انجامه
برا مثال قرار 10 درصد از حساب هر کارمند کم بشه و جدولی داریم به نام Account که ی فیلد شماره کارمند داره و ی فیلد Value
UPDATE Account SET Value=Value*.9

mtzstar
یک شنبه 03 شهریور 1392, 22:05 عصر
موسی جان ممنون از پاسخت
اما سواله من رو در حالتی در نظر بگیر که ما برای هر کارمند دو فیلد داریم که یکیش بدهکاری و دیگری بستانکاریه
حالا یه کارمند بدهکار هستش به صندوق و کارمند دیگر بستانکاری داره برنامه می بایست اگه بستانکاری داره کسر کنه از حساب و اگر بدهکاری داره به بدهکاری اضاف کنه
اگه یه کارمند بود به راحتی می تونستیم با دو فیلد بدهکاری و بستانکاری کار کرد با یه دستور آپدیت
اما مشکل اینجا اینه کار کردن با دو فیلد و با n کارمند هستش
حالا چطور میشه با دستوری که شما فرمودید این کارو کرد؟؟

mousa1992
دوشنبه 04 شهریور 1392, 02:12 صبح
سلام
توضیحاتی در مورد جدولی که ساختم طبق نمونه شما
فیلد ها : PID , Debt , Demand که در واقع شماره کارمند و مبلغ بدهی و طلبکاری رو نشون میده
این مثالی که میزنم طبق پروژه شماست و فک کنم دیگه مایل به تغییرش نباشین والا دیوار از همون اولش کجه ( دلیل حرفم اینه که نیاز به استفاده از دو فیلد برا نشون دادن بدهی و طلب نبود شما میتونستید خیلی راحت با مثبت و منفی این نتایج استنباط کنید )
و اما کد


DECLARE @Value int
SET @Value=20

UPDATE account SET Demand = case
when Demand = @Value then 0
when Demand > @Value then Demand - @Value
ELSE 0
END
, Debt = CASE
when Demand - @Value < 0 then Debt - Demand + @Value
ELSE Debt
END


من ی متغیر تعریف کردم به نام Value@ و بهش دستی مقداری رو دادم که شما باید اونو تو storedprocedure تعریف و توی برنامه بهش مقدار بدین
خب دستور اپدیت رو نوشتم که با استفاده از case تصمیم گیری میکنه که چه مقادیری رو برای Demand و Debt بفرسته - اگه مقدار Demand بزرگتر از Value باشه ینی اینکه کارمند ما طلب کار هست و مبلغ طلب اون بیشتر از مبلغی هست که قراره ازش کم کنیم پس به اندازه Value از Demand کم میکنیم اگه برابر باشه که میشه 0 و اما اگه کمتر باشه هم مقدارشو صفر در نظر میگیریم ( نکته : هنوز مقادیر رکورد اپدیت نشده ینی صفر به Demand نسبت داده میشه ولی نه الان ) خب میریم سراغ Debt ؛ برا اون هم عینا از case استفاده میکنیم و اگه Demand - Value کمتر از صفر باشه دقیقا همین مقدار رو باید به Debt اضافه کنیم در غیر این صورت هم که خود Debt میشه
برا افزودن مقدار هم میتونی مشابه همین ی procedure بنویسی

اما بازم نظرم اینه که جدول هاتو نرمال کنی تا به چنین مشکلاتی برخورد نکنی و تشکر میکنم ازتون چون باعث شدین مطالب جدید یاد بگیرم حین جواب دادن

موفق باشید

mtzstar
دوشنبه 04 شهریور 1392, 11:21 صبح
موسی جان از زحمتی که کشیدی بسیار تشکر می کنم
بانک من access هستش و محیط برنامه نویسی سی شارپ
مثالت خیلی عالی بود من این حالت رو قبلا تو سی شارپ پیاده سازی کرده بودم اینجور که میومد بدهکار و بستانکار رو بررسی می کرد و هر کردوم بزرگتر از صفر بود همون رو روالی که شما توی store procedure انجام دادی ،انجام می داد
مشکل من از اونجا سر چشمه گرفت که می بایست برای تمام کارمندان اینکارو انجام میداد من گفتم بیام با استفاده از خاصیت data row اینکارو انجام بدم که بیاد تمام کارمندان رو بررسی کنه البته میخوام از طریق محیط ویژوال باشه بدین صورت


DataTable dt = new DataTable("MyTable");
foreach (DataRow row in dt.Rows) { foreach (DataColumn column in dt.Columns) { if (row[column] != null) // this will checks the null values also if you want to check { // do what ever you want } } }

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


dr = con.Reader("SELECT * FROM [sandogh]");
if (dr.HasRows)
{
dr.Read();
double mojodi_sandogh = double.Parse(dr["bal"].ToString()) - double.Parse(txt_sh_profile.Text);
if (mojodi_sandogh > 0)
{
DontUseThisToCollapseSpaces(test.Text);
string text = test.Text;



str1 = "insert into kharj values('" + t2.Text + "','" + cmbdareje.Text + "','" + text + "','" + mtxtstartduty.Text + "','" + textBox1.Text + "','" + lbl_saham.Text + "')";
string str2 = "update sandogh set bal='" + mojodi_sandogh + "'";
con.execute(str1);
con.execute2(str2);
dr.Close();
cmbdareje.Text = null;
cmbdareje.Focus();;



}
if (mojodi_sandogh <= 0)
{
dr.Read();
double kk = Math.Abs(mojodi_sandogh);


dr = con.Reader("SELECT * FROM [sandogh]");
if (dr.Read())
{
if(dr["bedhkar"]!=DBNull.Value)
{
double t = Convert.ToDouble(dr["bedhkar"]);
t = t + kk;
string str2 = "update sandogh set bal='" + 0 + "',bedhkar='" + t + "'";
con.execute2(str2);

}
else
{
string str2 = "update sandogh set bal='" + 0 + "',bedhkar='" + kk + "'";
con.execute2(str2);

}

}

DontUseThisToCollapseSpaces(test.Text);
string text = test.Text;


str1 = "insert into kharj values('" + t2.Text + "','" + cmbdareje.Text + "','" + text +"','" + mtxtstartduty.Text + "','" + textBox1.Text + "','" + lbl_saham.Text + "')";

con.execute(str1);
dr.Close();
}



cmbdareje.Text = null;
cmbdareje.Focus();

}


else
{
dr.Read();
double mojodi_sandogh = 0 - double.Parse(txt_sh_profile.Text);

double k;
k = Math.Abs(mojodi_sandogh);
DontUseThisToCollapseSpaces(test.Text);
string text = test.Text;
MessageBox.Show(text);

str1 = "insert into kharj values('" + t2.Text + "','" + cmbdareje.Text + "','" + text +"','" + mtxtstartduty.Text + "','" + textBox1.Text + "','" + lbl_saham.Text + "')";

con.execute(str1);
string str3 = "insert into sandogh values('" + 0 + "','" + k + "')";

con.execute2(str3);




جدول من در اکسس البته اونایی که این کارها باید روشون انجام بشه
جدول تعریف کاربر هستش که من اومدم حساب هم همونجا تعریف کردم یعنی شامل فیلد های زیر هستن
nib_id(شماره کاربر)
nib_name(نام کاربر)
best(بستانکاری)
bede(بدهکاری)

و جدولی واسه مخارج هست که قرار است هر وقت خرجی صورت گرفت
برنامه بیاد تعداد کاربران رو گرفته و خرج مورد نظر رو تقسیم بر تعداد کاربران بکنه و این همون مبلغ ثابتی هست که من وقتی یه خرج رو در یه جدول ثبت می کنم همزمان می بایست
عمل بروزرسانی کسر از حساب کاربران صورت بگیره (همون چالشه من)
جدول مخارج به صورت زیر هستش
kharj_id
name
cost
date
discrib
div(این همون مبلغ ثابتی هستش که برنامه بدست آورده از تقسیم کاربران و میخواد از تمام کاربران این مبلغ رو کسر کنه)
بقیه فیلد ها فک می کنم مشخص باشن

mousa1992
دوشنبه 04 شهریور 1392, 11:36 صبح
اگه برا دستور UPDATE شرطی قرار ندی روی تمام رکورد ها عمل میکنه با این وضعیت بازم نوشتن چنین پروسیجری مشکلو حل نمیکنه ؟

mtzstar
دوشنبه 04 شهریور 1392, 11:44 صبح
بله دقیقا متوجه هستم
منم میخوام روی تمام رکورد ها این شرط اعمال بشه:لبخندساده:

mousa1992
دوشنبه 04 شهریور 1392, 11:51 صبح
مشکل من از اونجا سر چشمه گرفت که می بایست برای تمام کارمندان اینکارو انجام میداد من گفتم بیام با استفاده از خاصیت data row اینکارو انجام بدم که بیاد تمام کارمندان رو بررسی کنه البته میخوام از طریق محیط ویژوال باشه بدین صورت
خب طبق این گفته فک کردم که ...
راستی هیچ وقت صرفا برا گزارش گیری فیلدی رو به بانک اضافه نکن راه واسه گزارش گرفتن زیاده میتونی سورس گزارشتو از View و یا Object ها هم تامین کنی ...


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

mtzstar
دوشنبه 04 شهریور 1392, 12:05 عصر
مشکل اینجاست که بانکه من اکسس هستش و کوئری که شما فرمودین مربوط به اسکیول میشه(storedprocedure) رو چطور میشه تو اکسس اجرا کرد؟؟:متفکر:

mousa1992
دوشنبه 04 شهریور 1392, 12:31 عصر
شدنی که هست ! میشه از procedure برای Access هم استفاده کرد
لینک مطلب (http://accessexperts.com/blog/2011/07/29/sql-server-stored-procedure-guide-for-microsoft-access-part-1/)

ویرایش :
لزومی نداره که از stored procedure استفاده بشه ! کوئری رو بنویس و بجای Value از مقداری که باید کم بشه از هر کارمند استفاده کن حالا با textBox یا هرچیزی مقدارو بگیرو جایگزین کن دیگه

موفق باشی

mtzstar
دوشنبه 04 شهریور 1392, 12:53 عصر
ممنون موسی جان
ولی بهتر نبود به جای اینکه بریم حالا باز کلی تبدیلات storedprocedure رو تو اکسس یاد بگیریم
بیاییم از یه حلقه for استفاده کنیم تا ردیف ها رو بررسی کنه
یه مثال واضح تر در این مورد که میشه آورد و بنده نمونه ای پیدا نکردم
همون سیستم سود دهی بانک ها واسه هر مشتریه ولی اصلا نمونه پیدا نمیشه
کاش یه پروژه بود که همین کار که من می خواستم دقیقا انجام میداد
بدین صورت که:
اولش طبق همون روال ذخیره شده شما یا برنامه من میومد بستانکاری و بدهکاری رو بررسی می کرد و اون مبلغ رو کسر می کرد
دوم اینکه میرفت ردیف بعد واسه نفر بعدی اینکار رو انجام میداد
البته با اکسس و سی شارپ (که کد نویسیشم تماما تو سی شارپ باشه)
اگه مقاله یا پروژه ای در این مورد بدست آوردی خیلی ممنون میشم

mousa1992
دوشنبه 04 شهریور 1392, 13:08 عصر
System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection("Connectio string");
string query = "UPDATE account SET Demand = case when Demand >= {0} then Demand - {0} ELSE 0 END , Debt = CASE when Demand - {0} < 0 then Debt - Demand + {0} ELSE Debt END";
query = string.Format(query, txtValue.Text);
System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(query,connection) ;
connection.Open();
command.ExecuteNonQuery();
connection.Close();


من با provider های sql نوشتم شما با access بنویس توی کوئری که فرقی نمیکنن

mtzstar
دوشنبه 04 شهریور 1392, 13:50 عصر
موسی جان کوئری تو بدین حالت تغییر دادم (فقط نام فیلد هاشو)

string query = "UPDATE def_nibor SET best = case when best >= {0} then best - {0} ELSE 0 END , bede = CASE when best - {0} < 0 then bede - best + {0} ELSE bede END";
query = string.Format(query, lbl_saham.Text);
con.execute(query);

اما
خطای syntax میده؟!؟
Syntax error (missing operator) in query expression 'case when best >= 4000 then best - 4000 ELSE 0 END'.
میشه تو ویرایشش کمک کنی

mousa1992
دوشنبه 04 شهریور 1392, 14:24 عصر
نمیدونم چرا خطا میگیره ازتون و هرچی کوئریتونو بررسی میکنم مشکلی توش نمیبینم

SqlConnection connection = new SqlConnection(@"Data Source=MOUSA-PC\SQLEXPRESS;Initial Catalog=testDB;Integrated Security=True;Pooling=False");

string query = "UPDATE account SET Demand = case when Demand >= {0} then Demand - {0} ELSE 0 END , Debt = CASE when Demand - {0} < 0 then Debt - Demand + {0} ELSE Debt END";
query = string.Format(query, "200");
System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(query, connection);
connection.Open();
command.ExecuteNonQuery();
connection.Close();


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

ویرایش :
فک کنم مشکل در نحوه اجرا گرفتن کوئری باشه
کدتونو کامل قرار بدین ببینم چی شده
کوئری که داره اجرا میکنه داره مقدار 4000 رو از رشته best کم میکنه ! ینی مقادیر موجود توی جدول رو به جای best و bede قرار نداده فک کنم مشکل از همین باشه که برمیگرده به نحوه اجرا گرفتنتون

mtzstar
دوشنبه 04 شهریور 1392, 14:33 عصر
موسی جان میشه با access امتحان کنید و بسازید
و پروژتون آپ کنید
ببخشید که هی پشت سر هم تو زحمت میندازمتون:خجالت:

mtzstar
دوشنبه 04 شهریور 1392, 14:59 عصر
نمیدونم چرا خطا میگیره ازتون و هرچی کوئریتونو بررسی میکنم مشکلی توش نمیبینم

SqlConnection connection = new SqlConnection(@"Data Source=MOUSA-PC\SQLEXPRESS;Initial Catalog=testDB;Integrated Security=True;Pooling=False");

string query = "UPDATE account SET Demand = case when Demand >= {0} then Demand - {0} ELSE 0 END , Debt = CASE when Demand - {0} < 0 then Debt - Demand + {0} ELSE Debt END";
query = string.Format(query, "200");
System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(query, connection);
connection.Open();
command.ExecuteNonQuery();
connection.Close();


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

ویرایش :
فک کنم مشکل در نحوه اجرا گرفتن کوئری باشه
کدتونو کامل قرار بدین ببینم چی شده
کوئری که داره اجرا میکنه داره مقدار 4000 رو از رشته best کم میکنه ! ینی مقادیر موجود توی جدول رو به جای best و bede قرار نداده فک کنم مشکل از همین باشه که برمیگرده به نحوه اجرا گرفتنتون

موسی جان اگه منظورتو ممکنه اشکال از متد execute بنده باشه که من اونو از کلاس con فراخوانی می کنم ،اینو بگم من کل قسمت های برنامه مو از این طریق اجرا می کنم و مشکلی رخ نداده از این لحاظ خیالتون راحت اما بازم اگر خواستین میذارم واستون

mousa1992
دوشنبه 04 شهریور 1392, 15:05 عصر
اولین بار بود که از دیتابیس access استفاده میکنم اره همین خطایی که شما گفتین میده
بسرچ میکنم اگه تونستم رفعش کنم میگم خدمتتون

mtzstar
دوشنبه 04 شهریور 1392, 15:15 عصر
به به
میدونین منم همیشه از sql استفاده می کنم ولی دیدم این برنامم خیلی کوچیکه
نیاز نیست به اسیکول و البته همانطورکه میدونین access قابل حمل تر و کم دردسر تره(در بعضی موارد) نسبت به اسیکوله واسه این با اکسس نوشتم

منم طبق کد شما نوشتم
و باز همون خطا رو داد
OleDbConnection connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + "\\mtzstar.mdb");

string query = "UPDATE def_nibor SET best = case when best >= {0} then best - {0} ELSE 0 END , bede = CASE when best - {0} < 0 then bede - best + {0} ELSE bede END";
query = string.Format(query, lbl_saham.Text);
OleDbCommand command = new OleDbCommand(query, connection);
connection.Open();
command.ExecuteNonQuery();
connection.Close();


و اینم خطاش
باز مثله دفعه قبل
Syntax error (missing operator) in query expression 'case when best >= 2000 then best - 2000 ELSE 0 END'.

omidamiry
دوشنبه 04 شهریور 1392, 16:48 عصر
سلام

توجه داشته باشید که اکسس بانک اطلاعاتی نیست و مشکلات بعدی داره.

مهم نیست از اکسس استفاده میکنید یا sql وقتی با oledb دستورات sql رو ارسال میکنید جواب میده

چرا راه حل ساده رو سخت میکنید

مانده حساب شخص رو حساب کنید

مبلغ رو اضافه کنید


و بروز رسانی کنید

ضمنا معمولا تو اینجور حسابها که بد و بس داره لازم نیست بروز رسانی کنید فقط یه رکورد بد یا بس به مبلغ مورد نظر براش ثبت میکنید و براساس تاریخ سورت میکنی و زمانی به گرید ویو میدی همونجا مانده حساب رو حساب میکنی اینم کدش



select sum(bs)-sum(bd) from table


بازم سوالی داشتی در خدمتیم Md_amiry20@yahoo.com

mtzstar
دوشنبه 04 شهریور 1392, 17:17 عصر
ممنون امید جان از حسن توجهت




چرا راه حل ساده رو سخت میکنید

مانده حساب شخص رو حساب کنید

مبلغ رو اضافه کنید

و بروز رسانی کنید


کل مسئله بنده هم همینه گرفتن مبلغ مانده از حساب هر شخص کسر مبلغ مورد نظر
اما چالش بنده روی دو فیلد بود بله بنده میدونم که اگه یه فیلد بود مشکلی نبود
شما اگه واستون زحمتی نیست راه حلی ارائه بدید که بر اساس دو فیلد باشه چون برای بنده مهمه که عدد منفی وارد پایگاه داده نشده (حالا بخاطر مشکلات و مسائل جدید که بعدش ممکنه بوجود بیاد) به این خاطر بر اساس دوفیلد طراحی کردم
صورت سوال اینه حل مسئله بر اساس دو فیلد هستش(بدهکار و بستانکار) بعضی از افراد بدهی دارند و بعضی ها بستانکاری بدون اینکه عدد منفی وجود داشته باشه


ضمنا معمولا تو اینجور حسابها که بد و بس داره لازم نیست بروز رسانی کنید فقط یه رکورد بد یا بس به مبلغ مورد نظر براش ثبت میکنید و براساس تاریخ سورت میکنی و زمانی به گرید ویو میدی همونجا مانده حساب رو حساب میکنی اینم کدش

select sum(bs)-sum(bd) from table




در مورد کدوتون ممنون اما اگه میشه با توجه به صورت مسئله بنده اگه امکانش هست یه نمونه آپ کنید
د رضمن اینکه روشی که شما ارائه دادین که میاد جمع کل بستانکاری یه ستون رو می گیره منهای جمع کل ستون بدهکاری میکنه
در صورتی که این روش اشتباه چرا که حساب هر فرد متمایز از دیگریه
فرضا آقای x دارای 7000 تومن بستانکاریه
آقای x1 هم داراری 2000تومن بستانکاریه
و آقای y دارای 2000 بدهکاریه
طبق فرمول شما
:لبخندساده:=(2000)-(7000+2000)
که قطعا این جوابه بنده نیست!

با تشکر

omidamiry
سه شنبه 26 شهریور 1392, 09:21 صبح
دوست عزیز شما بعد از سلکت شرط نام یا کد برابر نام خاص یا کد خاص رو هم باید بنویسید دیگه همورو که من نباید بنویسم شما ره حل خواستید کد معادل رو که نخواستید

mtzstar
یک شنبه 31 شهریور 1392, 09:47 صبح
ممنون امید جان
مشکل رو حل کردم:چشمک: