View Full Version : کمک در نوشتن پرسجو
araz_pashazadeh
دوشنبه 18 مهر 1390, 12:04 عصر
با عرض سلام و خسته نباشید خدمت دوستان.
من در پایگاه داده دو تا جدول حساب بانکی و واریز نقدی را با هم جوین کردم تا موجودی کل را به دست بیاورم ولی در حساب بانکی فیلدی به نام موجودی اولیه دارم که با مبلغ فیش های ثبت شده جمع می شود.
مشکل کار از اینجا شروع میشه که اگه در جدول واریز نقدی برای این بانک رکوردی ثبت نشده باشه این بانک در لیست بانک ها قرار نمی گیره.
پرس و جوی من به این شکل هستش:
SELECT TBLBankAccount.AccountID, TBLBankAccount.BankName, TBLBankAccount.AccountNumber, CONVERT(decimal(10, 0), TBLBankAccount.Cash)
+ SUM(CONVERT(decimal(10, 0), TBLReceipt.Payment)) AS Cash, TBLBankAccount.Description
FROM TBLBankAccount INNER JOIN
TBLReceipt ON TBLBankAccount.AccountID = TBLReceipt.AccountId
GROUP BY TBLBankAccount.AccountID, TBLBankAccount.BankName, TBLBankAccount.AccountNumber, TBLBankAccount.Cash, TBLBankAccount.Description
اگه دوستان قبلا با همچین مشکلی مواجه شدن ممنون میشم اگه من را هم راهنمایی کنن.
یوسف زالی
دوشنبه 18 مهر 1390, 13:16 عصر
سلام.
چرا از left join استفاده نمی کنید؟
araz_pashazadeh
دوشنبه 18 مهر 1390, 18:52 عصر
سلام.
چرا از left join استفاده نمی کنید؟
دوست عزیز من از این روش به صورت زیر استفاده کردم برای حسابهای که فیش برای آنها ثبت شده جمع مبلغ ها را درست می اورد ولی برای حسابهای که فیش برای آنها ثبت نشده موجودی اولیه را NULL می اورد
SELECT TBLBankAccount.AccountID, TBLBankAccount.BankName, TBLBankAccount.AccountNumber, CONVERT(decimal(10, 0), TBLBankAccount.Cash)
+ SUM(CONVERT(decimal(10, 0), TBLReceipt.Payment)) AS Cash, TBLBankAccount.Description
FROM TBLBankAccount LEFT OUTER JOIN
TBLReceipt ON TBLBankAccount.AccountID = TBLReceipt.AccountId
GROUP BY TBLBankAccount.AccountID, TBLBankAccount.BankName, TBLBankAccount.AccountNumber, TBLBankAccount.Cash, TBLBankAccount.Description[/SQL
به همین دلیل من این مشکل را با استفاده از مفهوم مجموعه ها به شکل زیر انجام دادم که یک راه حل بسیار پر هزینه ای هستش:
[SQL]SELECT TBLBankAccount.AccountID, TBLBankAccount.BankName, TBLBankAccount.AccountNumber, CONVERT(decimal(10, 0), TBLBankAccount.Cash)
+ SUM(CONVERT(decimal(10, 0), TBLReceipt.Payment)) AS Cash, TBLBankAccount.Description
FROM TBLBankAccount INNER JOIN
TBLReceipt ON TBLBankAccount.AccountID = TBLReceipt.AccountId
GROUP BY TBLBankAccount.AccountID, TBLBankAccount.BankName, TBLBankAccount.AccountNumber, TBLBankAccount.Cash, TBLBankAccount.Description
UNION
(SELECT AccountID, BankName, AccountNumber, Cash, Description
FROM TBLBankAccount
EXCEPT
SELECT TBLBankAccount.AccountID, TBLBankAccount.BankName, TBLBankAccount.AccountNumber, TBLBankAccount.Cash, TBLBankAccount.Description
FROM TBLBankAccount INNER JOIN
TBLReceipt ON TBLBankAccount.AccountID = TBLReceipt.AccountId
GROUP BY TBLBankAccount.AccountID, TBLBankAccount.BankName, TBLBankAccount.AccountNumber, TBLBankAccount.Cash, TBLBankAccount.Description)
در ضمن دوست عزیز لازم هستش من تمام فیلدهای که در سلکت هست را در قسمت گروه بندی بیارم؟
این برام همیشه یک سئوال مبهم بوده....
یوسف زالی
دوشنبه 18 مهر 1390, 20:52 عصر
ببینید وقتی داده های عددی با هم جمع می شن ، حتی اگر یکی از اونها Null باشه حاصل Null میشه.
راه چاره اینه که از تابع IsNull استفاده کنیم و در حقیقت sum(isnull(field, 0)) -- test رو استفاده کنیم.
اما در مورد گروه یندی اجازه بدید با یک مثال ساده مطلب رو یاد بگیریم:
فرض کنید در هر روز چندین قرار ملاقات در Reminder گوشی خودتون دارید.
این قرار ها ممکنه با اشخاص تکراری باشند.
حالا این سوالات رو جواب بدید:
1- تمام قرار های شما چند تاست؟
select count(1) from Reminder
2- در هر روز چند قرار دارید؟
select count(1), Date from Reminder GROUP BY DATE
در مثال دوم گروه بندی وجود داره. به کلمات "در هر روز" دقت کنید. این یعنی به تفکیک روز اطلاعاتی رو می خواهید. (بر اساس روز - گروه بندی شده با روز)
خب حالا اگر من بگم که در کنار تعداد و روز بگید با چه کسانی قرار دارید، شما چه جوابی می دید؟
اینجا ما دچار سردرگمی می شیم که اسم کدوم شخص در کنار روز مربوطه بیاد. (دقت کنید قراره گروه بندی فقط بر اساس روز باشه. وقتی بر اساس چیزی گروه بندی می کنیم، در خروجی اون چیز به ازای هر ردیف باید منحصر به فرد باشه. اگر چه ممکنه گروه ترکیبی باشه اما خود ترکیب هم در نهایت در هر ردیف یونیک هست.)
دو تا راه داریم:
یا باید گروه بندی رو توسعه بدیم به روز و شخص - که در این صورت ممکنه روز تکرار بشه (اما ترکیب روز و شخص تکرار نمی شه)
یا باید از بین لیست اشخاص هر روز یکی رو انتخاب کنیم. مثلا بگیم که اولین نفر رو بیار (در اینجا مثلا از لحاظ الفبایی - به دلیل ساده شدن مثال)
راه اول:
select count(1), date, person from Reminder group by date, person
زاه دوم:
select count(1), date, min(person) from Reminder group by date
خلاصه مطلب اینکه:
در گروه بندی "فیلد"های انتخاب شده یا باید در توایع تجمیعی (Aggregate) بیایند (count, sum, avg, min, max, ...) یا باید جزو گروه بندی باشند.
امیدوارم تونسته باشم مطلب رو رسونده باشم.
موفق باشید.
araz_pashazadeh
چهارشنبه 20 مهر 1390, 11:45 صبح
از این که من را در این زمینه راهنمایی کردین ممنون هستم ولی من سئوال دیگری داشتم شاید جایی این سئوال در این قسمت نباشه ولی چون راهنمایی شما جامع بود به همین دلیل در این قسمت مطرح می کنم.
من در واسط کابری قسمت های که لازم هستش کاربر تاریخ وارد نمایید من خودم به صورت پیش فرض تاریخ سیتم را با استفاده از Persia.dll تبدیل به تاریخ فارسی می کنم و در اختیار کاربر قرار می دم و در پایگاه داده هم ذخیره مکنم تا اینجای کار مشکلی ندارم و کدی که من استفاده می کنم به صورت زیر می باشد:
// Getting today date and converting it to Persian date
txtDateReceive.Text = Persia.Calendar.ConvertToPersian(DateTime.Now).Sim ple;
مشکل از اینجا شروع میشه که وقتی من می خوام براساس تاریخ جستجو کنم و یا تاریخ را خودم وارد کنم یا ویرایش کنم در این صورت تاریخ در واسط کاربری به صورت فارسی نمایش داده میشه (چون من زبان صفحه را فارسی کردم) ولی وقتی در دیتا بیس ذخیره میشه اون قسمتی که من وارد کردم انگلیسی هستش و قسمتی که توسط این تابع وارد شده فارسی به همین دلیل جستجو هم با مشکل مواجه میشه چون مقداری که من وارد میکنم درست فارسی نمایش داده میشه ولی به دیتا بیس به صورت انگلیس ارسال میشه در واقع قسمتی از تاریخ به صورت فارسی هستش(بخشی که توسط تابع برگردانده شده و دستکاری نشده)و قسمتی به صورت انگلیسی(کاربر وارد کرده)و در پایگاه داده هم به همین صورت ذخیره میشه(بخشی از تاریخ فارسی و بخش دیگه به صورت انگلیسی)راه حل این مشکل چیه؟
دلیل این مشکل من چه چیزی می تونه باشه؟
من هر کاری کردم به نتیجه نرسیدم.
یوسف زالی
پنج شنبه 21 مهر 1390, 02:25 صبح
من مشکل شما رو تا به حال بهش برنخوردم.
اما حدسم اینه که کولیشن ها با هم تفاوت دارند.
خروجی تابع رو قبل از ذخیره تبدیل کنید به فرمتی که می خواهید.
متاسفانه نمی تونم بیشتر از این کاری کنم.
چیزی در باره مشکلتون نمی دونم.
araz_pashazadeh
پنج شنبه 21 مهر 1390, 16:24 عصر
من مشکل شما رو تا به حال بهش برنخوردم.
اما حدسم اینه که کولیشن ها با هم تفاوت دارند.
خروجی تابع رو قبل از ذخیره تبدیل کنید به فرمتی که می خواهید.
متاسفانه نمی تونم بیشتر از این کاری کنم.
چیزی در باره مشکلتون نمی دونم.
دوست عزیز همین که شما راهنمایی کنین چطوری می تونم قبل از ذخیره داده در پایگاه داده اعداد را از حروف فارسی به انگلیسی تبدیل کنم به نظر من مشکل حل میشه؟
یعنی عدد یک که هست به صورت کاراکتر انگلیسی ذخیره بشه نه کاراکتر فارسی.
یوسف زالی
پنج شنبه 21 مهر 1390, 23:46 عصر
تست کنید ببینید اعداد در تابع Unicode چه خروجی ای دارند.
select Unicode('1') as X
اگر متفاوت بود قبل از ذخیره با replace جای اونها رو عوض کنید.
insert into TBL values(replace(@Str, nchar(code of that unicode return), '1')) -- test
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.