PDA

View Full Version : نوشتن کوئری چندین شرط



moslehif
سه شنبه 12 اسفند 1393, 09:33 صبح
با سلام خدمت دوستان و اساتید

من میخوام توی یک فرم جستجو یا ریپورت کاربر چندین شرط جستجو رو انتخاب و یا انتخاب نکنه چطور باید این کد رو بنویسم. من الان نهایتا میتونم یک یا دو شرط رو برسی کنم. چطوری توی کوئری مورد نظر if بزارم.

مثلا select id from table1 where date=maskedit1.text and name=edit1.text
شاید نام را وارد نکرده باشه
حالا این 2 مورد بود

فکر کنید من یک همچین حالتی داشته باشم

از تاریخ تا تاریخ
از کد تا کد
از شماره حساب تا شماره حساب

یا خیلی بیشتر از این موارد که محدود بشه یا نشه
شاید کاربر انتخاب کرد یا نکرد این موارد رو

یعنی توی کوئری شرط چجوری بزارم ؟؟؟

ممنون میشم راهنمایی کنید

farzadkamali
سه شنبه 12 اسفند 1393, 10:58 صبح
با سلام خدمت دوستان و اساتید

من میخوام توی یک فرم جستجو یا ریپورت کاربر چندین شرط جیتجو رو انتخاب و انتخاب نکنه چطور باید این کد رو بنویسم. من الان نهایتا میتونم یک یا دو شرط رو برسی کنم. چطوری توی کوئری مورد نظز if بزارم.

مثلا select id from table1 where date=maskedit1.text and name=edit1.text
شاید نام را وارد نکرده باشه
حالا این 2 مورد بود

فکر کنید من یک همچسن حالتی داشته باشم

از تاریخ تا تاریخ
از کد تا کد
از شماره حساب تا شماره حساب

یا خیلی بیشتر از این موارد که محدود بشه یا نشه
شاید کاربر انتخاب کرد یا نکرد این موارد رو

یعنی توی کوئری شرط چجوری بزارم ؟؟؟

ممنون میشم راهنمایی کنید

باید از دستورات sql در کوئری تون استفاده کنید. یه مثال میزنم :


adoquery1.close
adoquery1.sql.text:="select * from table1 where date>=:date1 and date<=:date2 and name=:name1"
adoquery1.parameters.parambyname('date1').value:=e dit1.text
adoquery1.parameters.parambyname('date2').value:=e dit2.text
adoquery1.parameters.parambyname('name1').value:=e dit3.text
adoquery1.open

farzadkamali
سه شنبه 12 اسفند 1393, 11:07 صبح
حالا قبل از این دستورات باید edit های 1 و 2 و 3 رو در خود دلفی چک کنید ببینید خالی هست یا نه . اگر خالی بود پیغام مناسب رو چاپ کنه.(این دیگه توی خود دلفی انجام میشه و کاری به sql و کوئری نداره)

golbafan
سه شنبه 12 اسفند 1393, 12:02 عصر
سلام میتونید اولین شرط رو بزارید id>0 بعد با چک کردن edit ها اگر خالی نبودن کوئری بسازید

مثال:

adoquery.text:='select * from table where id>0';
if trim(edit1.text)<>'' then
adoquery.add('and name='+edit1.text);
if maskedit1.text<>'' then
adoquery.add('and date='+ maskedit1.text);

یوسف زالی
سه شنبه 12 اسفند 1393, 12:19 عصر
سلام.
روش درست این کار جور دیگه هست.



میتونید اولین شرط رو بزارید id>0

معمولا می گذارن 1 = 1

برای این کار چیزی مشابه زیر باید بنویسید:


where
(DateParam = '' or DateParam between D1 and D2)
and
(IntParam = 0 or YourField = IntParam) /* other way: IntParam in (0, YourField) */
and
(IntParam2 = 0 or YourField = IntParam2)
and ..


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

Mahmood_M
سه شنبه 12 اسفند 1393, 16:25 عصر
شخصا ترجیح میدم شرطها رو در ابتدا چک کنم و متناسب با اینکه چه شرطی برقرار هست ، متن کوئری رو کامل کنم ، مثال :
فرض کنیم یک مقدار پایه برای کوئری در نظر گرفته شده ، مثلا :
"SELECT * FROM MyTable"
وقتی درخواست گرفتن کوئری داده شد ، شرطها رو چک می کنیم و متناسب با اون ، متن کوئری رو کامل می کنیم
فرض کنید برای 3 فیلد MCaption و MCount و MDate می خوایم یک فیلتر ترکیبی ایجاد کنیم ، MCaption می تونه یک رشته باشه ، MCount مقدار بین دو عدد و MDate مقدار بین دو تاریخ
برای هر کدوم یک CheckBox و Edit ( یا هر کنترلی برای دریافت ورودی ) می ذاریم و قبل از MCount و همینطور قبل از MDate ، یک ComboBox می ذاریم که مشخص کنه مقدار این فیلد با شرط قبلی AND بشه یا OR بشه ، بدیهیه که اگر قبل از MCount یا قبل از MDate شرطی ثبت نشده باشه ( یعنی مقدار متن کوئری برابر مقدار پیشفرض باشه ) باید از مقدار ComboBox صرفه نظر کنیم و بدون توجه به اون شرط رو بسازیم ، به کدهای زیر دقت کنید ، منطقش رو ببینید :

var
FText, AndOr : String;
begin
FText := MSQLDefault;

if MCaptionChBox.Checked then
begin
if Trim(MCaptionEdit.Text) = '' then
begin
MessageBox(Handle, 'عنوان را وارد نمایید', '', MB_OK+MB_ICONEXCLAMATION);
Exit;
end;

FText := FText + ' WHERE MCaption LIKE ' + QuotedStr('%'+Trim(MCaptionEdit.Text)+'%');
end;

if MCountChBox.Checked then
begin
if Trim(MCountFromEdit.Text) = '' then
begin
MessageBox(Handle, 'شروع بازه ی تعداد را وارد نمایید', '', MB_OK+MB_ICONEXCLAMATION);
Exit;
end;

if Trim(MCountToEdit.Text) = '' then
begin
MessageBox(Handle, 'پایان بازه ی تعداد را وارد نمایید', '', MB_OK+MB_ICONEXCLAMATION);
Exit;
end;

if StrToInt(MCountFromEdit.Text) > StrToInt(MCountToEdit.Text) then
begin
MessageBox(Handle, 'بازه ی تعداد نامعتبر است', '', MB_OK+MB_ICONEXCLAMATION);
Exit;
end;

if FText = MSQLDefault then
FText := FText + ' WHERE MCount BETWEEN ' + Trim(MCountFromEdit.Text) + ' AND ' + Trim(MCountToEdit.Text)
else
begin
case MAndOrCBox1.ItemIndex of
0 : AndOr := ' AND ';
1 : AndOr := ' OR ';
end;
FText := FText + AndOr + 'MCount BETWEEN ' + Trim(MCountFromEdit.Text) + ' AND ' + Trim(MCountToEdit.Text)
end;
end;

if MDateChBox.Checked then
begin
if Trim(MDateFromDP.Text) = '' then
begin
MessageBox(Handle, 'شروع بازه ی تاریخ را وارد نمایید', '', MB_OK+MB_ICONEXCLAMATION);
Exit;
end;

if Trim(MDateToDP.Text) = '' then
begin
MessageBox(Handle, 'پایان بازه ی تاریخ را وارد نمایید', '', MB_OK+MB_ICONEXCLAMATION);
Exit;
end;

if StrToDate(MDateFromDP.ConvertDate) > StrToDate(MDateToDP.ConvertDate) then
begin
MessageBox(Handle, 'بازه ی تاریخ نامعتبر است', '', MB_OK+MB_ICONEXCLAMATION);
Exit;
end;

if FText = MSQLDefault then
FText := FText + ' WHERE MDate BETWEEN ' + DM.DateForSQL(MDateFromDP.ConvertDate) + ' AND ' + DM.DateForSQL(MDateToDP.ConvertDate)
else
begin
case MAndOrCBox2.ItemIndex of
0 : AndOr := ' AND ';
1 : AndOr := ' OR ';
end;
FText := FText + AndOr + 'MDate BETWEEN ' + DM.DateForSQL(MDateFromDP.ConvertDate) + ' AND ' + DM.DateForSQL(MDateToDP.ConvertDate)
end;
end;

if FText <> MSQLDefault then
begin
DM.MQuery.DisableControls;
DM.MQuery.Active := False;
DM.MQuery.SQL.Text := FText;
DM.MQuery.Active := True;
DM.MQuery.EnableControls;
end
else
MessageBox(Handle, 'مقداری برای جستجو وارد نشده است', '', MB_OK+MB_ICONEXCLAMATION);


می تونید با بررسی بیشتر شرطها ، جستجوی هوشمند تری بسازید
مشاهده تصویر نمونه ای که ضمیمه کردم ، به درک بهتر کمک می کنه

* تابع DateForSQL مقدار تاریخ رو به فرمت صحیح SQL Server در میاره که اهمیتی نداره و منطق قضیه مهمه !

موفق باشید ...

یوسف زالی
سه شنبه 12 اسفند 1393, 17:53 عصر
روش بدی نیست ولی در کوئری های داخل ADOStoredProd کارساز نیست.

moslehif
سه شنبه 12 اسفند 1393, 20:43 عصر
ممنون از تمام دوستان که وقت گذاشتند و راهنمایی کردن.تقریبا فهمیدم باید چیکار کنم.

Mahmood_M
چهارشنبه 13 اسفند 1393, 14:24 عصر
روش بدی نیست ولی در کوئری های داخل ADOStoredProd کارساز نیست.
داریم یک دستور SQL می سازیم ، مزاحمتی برای سایر دستورات ایجاد نمیشه ، خروجی ما یک WHERE ساده هست ، کارساز بودن یا نبودن مطرح نیست !
منظورتون رو با یک مثال برسونید

یوسف زالی
چهارشنبه 13 اسفند 1393, 15:40 عصر
شرح ایراد وارده هنگام کار با SP:
تصور کنید یک StoredProcedure مثلا در SQL دارید (یا هر DBMS دیگه ای که می شه توش تعریف کرد)
این SP پارامتر رو فقط می شناسه نه کوئری، اما در دل خودش کوئری هست که ران می شه.
ما برای ساخت چنین SP هایی باید تمام شرایط و حتی انتخاب نشدن شرایط توسط یوزر رو هم بررسی و پیاده کنیم.
رابط بین یوزر و SP فقط همین پارامترها هستند.
این تنها راه ممکن نیست ولی می شه گفت Best Practice برای نمونه های این چنینی هست.
راه دیگه برای چنین مثالی که من زدم، ساخت کوئری در حالت داینامیکه، که خب ایراد بزرگش ذخیره نشدن Execution Plan در دی بی هست.
به دلایلی که در بالا اشاره کردم برای این موارد استفاده از کوئری های مدل معرفی شده رو توصیه می کنم.

Mahmood_M
چهارشنبه 13 اسفند 1393, 16:58 عصر
چیزی که عنوان کردید ارتباطی به سوال پرسیده شده و جواب داده شده نداره
سناریو : قصد داریم جدول رو بر اساس چند فیلد فیلتر کنیم و باید شرایط مختلف ورودی ها چک بشه
یکی از راه حل ها : ابتدا چک کردن مقادیر ورودی ها و ساخت یک WHERE CLAUSE متناسب با ورودی های داده شده
برای سناریو های دیگه می تونید از روشهای دیگه استفاده کنید
معمولا هیچ روش ثابت و یکتایی برای یک سناریو وجود نداره و اکثر روشهای استفاده شده کاملا سلیقه ایه و به خلاقیت برنامه نویس مربوط میشه
چیزی که بدیهیه ، اینه که وقتی برنامه نویس از یک زبان و محیط برنامه نویسی برای ساخت برنامه استفاده میکنه ( Delphi ) ، اگر مدیریت بخشهای مختلف اون رو به ابزارهای فرعی ( SQL ) بسپره ، مدیریت سورس مشکل تر ، خوانایی برنامه کمتر و عیب یابی کد سخت تر میشه
این خود برنامه نویسه که باید توانایی گرفتن برآیند از فاکتورهای بالا به علاوه فاکتورهای دیگه مثل سرعت و ... رو داشته باشه و درنهایت تشخیص بده که بهتره از چه روشی استفاده کنه
نکته ی آخر : شخصا سعی می کنم تا حد امکان صافی ها رو قبل از رسیدن به SQL بزارم ! ، و داده هایی که درون دستورات SQL وارد میشه کمترین نیاز به بررسی رو داشته باشه ، شخص دیگه ای می تونه جور دیگه ای عمل کنه اما هر روشی که به کار ببره ، لزوما اسمش "روش درست" نیست !

موفق باشید ...

یوسف زالی
چهارشنبه 13 اسفند 1393, 22:24 عصر
همون طور که بالاتر گفتم روش مورد نظر برای StoredProcedure ها کاساز نیست نه کوئری ها.
این به این معنیه که روش گفته شده برای کوئری ها می تونه روش درستی باشه و در مواردی هم هست.
این که شرایط در دلفی چک بشه، درسته، اما ارتباطی به بحث جاری نداره دوست عزیز.
مساله چک شدن یا نشدن پارامتر نیست، مساله خود پارامتره.
برای مسایل مختلف راه حل های متنوعی وجود داره که انتخاب اون به تحلیل برنامه نویس بستگی داره.
شرایطی مثل سرعت، امنیت، سادگی دیباگ، و گسترش پذیری و البته چندگانگی عملکرد و اختصاصی شدن راحت تر در روش StoredProcedure یا مزایای روش های دیگه..
برای برنامه های دو لایه که در حال حاضر بیشترین حجم برنامه های شرکت های بزرگ رو تشکیل می دن (با دلفی، لااقل تا جایی که بنده ارتباط دارم) استفاده از روشی که ذکر شد رواج داره.
بنده هم نگفتم چه روشی غلطه، گوشزد کردم که این روش فقط در کوئری های سمت UI جوابگوست.
سوال پرسیده شده پتانسیل آموزش ضمنی رو داشت، برای همین مورد جنبی گفته شد.

موفق و موید باشید.

benyaminrahimi
پنج شنبه 14 اسفند 1393, 15:27 عصر
برای این منظور بدون کد نویسی میتونید از کامپوننت cxfilter از سری devexpres و یا cxdbnavigator و یا cx گرید استفاده کنید که تمام فیلد ها و عمل گر ها رو هندل میکنند برای اینکه نتیجه در خروجی دیتا ست هم همسان شه باید پراپرتی autodatasetfilter رو true ست کنید ... این کامپوننت فارغ از sql اسن عملیات رو انجام میده و در result های stored procedure نیز عمل میکنه

129134

moslehif
شنبه 16 اسفند 1393, 21:02 عصر
برای این منظور بدون کد نویسی میتونید از کامپوننت cxfilter از سری devexpres و یا cxdbnavigator و یا cx گرید استفاده کنید که تمام فیلد ها و عمل گر ها رو هندل میکنند برای اینکه نتیجه در خروجی دیتا ست هم همسان شه باید پراپرتی autodatasetfilter رو true ست کنید ... این کامپوننت فارغ از sql اسن عملیات رو انجام میده و در result های stored procedure نیز عمل میکنه

129134

با سلام ممنون از شما دوست عزیز
ولی فکر می کنم این روش شما برای فیلتر اطلاعات select شده باشه در صورتی که ما میخواهیم خود select با محدودیت و فیلتر انجام بشه.