PDA

View Full Version : جستجو در چندین ستون رشته ای



release2008
پنج شنبه 10 مرداد 1387, 21:52 عصر
من یک جدول دارم که دارای حدود 20 ستون رشته ای است که هر کدام به طور میانگین حدوداً به طول 30 کاراکتر می باشد! کاربر امکان جستجو در تمام ستون ها را از من می خواد.
می خواستم بدونم که من جستجوی خودمو با یک کدی مثل زیر بنویسم



SELECT * FROM tb1 WHERE (@col1='' OR col1 like '%'+@col1+'%') and ...
یا ستون رشته ای اضافی بگیرم شامل همه رشته های اون 20 تا ستون و با استفاده از fulltext فقط روی این ستون جستجو را انجام بدم!

یا اگر راهش اصلاً یک چیز دیگه است .... که لطف می کنید راهنماییم کنید

یک سوال دیگه هم داشتم، من 4 تا 5 نوع کالا دارم که اینها فیلدهاشون کلاً با هم فرق داره ولی هرکدام اکثر فیلدهاشون رشته است. می خواستم بدون آیا بهتره واسه هرکدام از این کالاها یک جدول اختصاص بدم و یا یک جدول کلی بگیرم و ستون های هم نوع و اندازه را روی هم map کنم با توجه به این موضوع:
که از هرکدام از این کالاها حدوداً 30,000 تا وجود داره و قرار جستجوی بالا روی آنها انجام گیرد !

اگر قرار شد جدول ها جدا باشند، جستجو کلی روی همه جدول ها چطور باشه؟

امیدوارم از راهنمایی خودتون منو محروم ننمایید

رضا عربلو
جمعه 11 مرداد 1387, 14:44 عصر
یک جدول جدید بساز با نام Strings با دفیلد ID از نوع int که PK است و فیلد Str از نوع NVARCHAR
حالا مقادیر رشته ای در جدول tb1 را در جدول دوم بریز. اینطوری به راحتی می توانی شرط WHERE ات را تنها بر روی فیلد str جدول دوم بگذاری .

release2008
جمعه 11 مرداد 1387, 18:00 عصر
اینم که گفتین ایده جالبی به نظر می رسه، به ذهن خودم نرسیده بود! ممنون
یعنی شما می گید در جدولی با 5(نوع کالا) * 20(تعداد فیلد های هر کالا) * 30,000 (تعداد هر نوع کالا)= 3,000,000 رکورد، دستور like در قسمت where مشکلی به وجود نخواهد آورد؟


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

رضا عربلو
جمعه 11 مرداد 1387, 20:07 عصر
بطور کلی بستگی به نوع کوئری تان و نحوه استفاده از شرط WHERE دارد و اینکه آیا از ایندکس ها به نحو مناسب استفاده می شود.
ولی با استفاده از امکانات FullText index به راحتی می توانید کوئری هایتان را بگیرید.
http://www.google.com/url?sa=t&ct=res&cd=1&url=http%3A%2F%2Fwww.developer.com%2Fdb%2Farticle. php%2F3446891&ei=szOTSOzcNZDWQPnD7bAK&usg=AFQjCNEZ5jVR4gk1Fh9ltw6iMdYyGRZBnQ&sig2=ZUgSCAWsC2ZSYlFVltK15A

release2008
جمعه 11 مرداد 1387, 20:57 عصر
ممنون آقای عربلو
مقاله رو خوندم ولی اگر بخوام از fulltext استفاده کنم باید دستور Contains را برای هر ستون استفاده کنم؟؟؟ یعنی

SELECT *
FROM tb1
WHERE CONTAINS(Col1, '"value1"') OR CONTAINS(Col2, '"value2"') OR ....
یا دستوری داره که روی تمام ستون های داخل اون کاتالوگ fulltext همزمان جستجو کنه؟
و اگر دستوری ندارد، اون روشی که تو پست اول گفتم که ستونی رشته ای تعریف کنم و داخلش تمام ستون های رشته ای را بریزم (طولش می شه حدود 600 کاراکتر) و fulltext را روی اون تعریف کنم و فقط روی اون از دستور Contains استفاده کنم!

راستی یک سری مقاله پیدا کردم . خوشحال می شم نظرتو راجع به اونا با توجه به پروژه خودم بدونم
http://vyaskn.tripod.com/search_all_columns_in_all_tables.htm
http://www.mssqltips.com/tip.asp?tip=1522
http://code.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=NonDynamicSearch

رضا جاسبی
شنبه 12 مرداد 1387, 00:53 صبح
من با روش آقای عربلو مخالفم. (شرمنده ام)
چون با ترکیب چندین رشته که در واقع ترکیب چندین فیلد هست باعث می شیم که فیلدها از حالت اتمیک خارج بشن و اصولا نرمال سازی رو رعایت نکرده باشیم. چنین جدولی 1nf هم نیست.
من فکر می کنم راه حلی که در پست اول گفتید جواب میده. یعنی برای تک تک ستونها از Like استفاده کنی. البته فکر می کنم در برنامه می تونی اگر مقداری برای جستجو در ستون مورد نظر داشتی اضافه کنی.
یک تکه متن ضمیمه کردم. برای جستجو در یک فرم در #C که امیدوارم به دردتون بخوره.
یک متن رو به عنوان commandText می سازیم و بعد اون رو به عنوان متن Query استفاده می کنیم.
امتحان هم کردم. اینکه چند تا فیلد متنی رو مستقل در Query بیاوریم سریعتر است تا همه را ادغام کنیم و یک فیلد کلی تشکیل بدیم و بعد در Query بیاوریم. البته صحبت از یکی و ده تا رکورد نیست. بحث سر صدها هزاره.

release2008
شنبه 12 مرداد 1387, 02:08 صبح
جناب جاسبی یعنی شما یک where claus با 20 تا شرط که با هم or شدن را پیشنهاد می کنید؟ مشکلی به وجود نمیاد؟

من دستور زیر را در لینک که بعدش گذاشتم پیدا کردم! یعنی تمام ستون های رشته ایم را (20تا) در fulltext قرار بدم بعد دستور زیر را استفاده کنم.

SELECT product_name, isbn FROM products
WHERE CONTAINS (*, 'catalog OR "full-text index" ')

http://www.informit.com/articles/article.aspx?p=21640

می دونید می خوام از اینکه تو این شرایط استفاده از where claue و دستور like بهینه است یا استفاده از fulltext ؟ یا به کل یه راه دیگه؟ مطمئن بشم.

AminSobati
شنبه 12 مرداد 1387, 13:18 عصر
دوست عزیزم،
استفاده از OR در شرط باعث میشه SQL Server از ایندکس استفاده نکنه و Table Scan اتفاق بیافته (البته استثناهایی هم وجود داره، کاملا وابسته به Query هست). خوبیه FTS اینه که میتونین در Contains از * استفاده کنین برای فیلدهای که در FTS شرکت دارند.
همچنین در شرایطی که تعداد ORها محدود و فیکس هستند، ما از نوشتن Queryهایی که با هم UNION میشن نتیجه بسیار خوبی از دیدگاه Performance گرفتیم:

select * from t1 where col1=myvalue1
union
select * from t1 where col1=myvalue2
union....

ولی همه اینها برمیگرده به شکل دقیق Query شما که با دیدن Execution Plan اون میشه نظر قطعی داد

ASKaffash
شنبه 12 مرداد 1387, 14:23 عصر
سلام
یک راه حل اینست که ستونی که خالی است را در دستور Select وارد نکنید و یک رشته شامل Select بسازید و با استفاده از EXEC اجرا کنید مثلا این مثال روش استفاده از EXEC را به شما نشان میدهد :





Declare @x Int,@y Int,@S VarChar (4000)
Set @x = 10
Set @y = 20
Set @S='Select '+Convert(VarChar(10),@x)+'+'+Convert(VarChar(10), @y)
EXEC(@S)

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

release2008
شنبه 12 مرداد 1387, 14:37 عصر
آقای ثباتی ممنونم از همفکریتون!
ولی من علی رغم راهنمایی شما و دیگر دوستان نتونستم یک راه حل قطعی را پیدا کنم!(شاید شما ها گفتید من درک نکردم)

آقای ثباتی من اگر از روش شما استفاده کنم باید یک کوئری که 100 تا select داره(به خاطر 5 تا جدول هرکدام 20 ستون دارند) به وجود میآد! فکر می کنید کارایشو حفظ می کنه؟ تازه من از عملگر like به جای = شما باید استفاده کنم؟؟

حالا اگر من بیام 5 کاتالوگ fulltext روی 5 تا جدول که هرکدام شامل اون 20 تا ستون رشته ای باشه و برای جستجو روی همه ستون های رشته ای این 5 تا جدول دستور زیر مناسب تر به نظر نمی رسه؟؟؟؟؟؟


SELECT id,Name FROM table1
WHERE CONTAINS (*, '"searchvalue"')
union
SELECT id,Name FROM table2
WHERE CONTAINS (*, '"searchvalue"')
union
SELECT id,Name FROM table3
WHERE CONTAINS (*, '"searchvalue"')
union
SELECT id,Name FROM table4
WHERE CONTAINS (*, '"searchvalue"')
union
SELECT id,Name FROM table5
WHERE CONTAINS (*, '"searchvalue"')

AminSobati
شنبه 12 مرداد 1387, 19:28 عصر
همونطور که عرض کردم به Query شما بستگی داره. از پست قبلی مشخصه شما میخواین جستجوی محتوی متون در کل دیتابیس رو راه اندازی کنید. طبیعیه که در این حالت، با زیاد بودن تعداد جداول، Queryهای زیادی هم لازمه. روشی که در بعضی پورتالها دیدم استفاده کرده اند، ذخیره کردن تکراری متون در یک جدول واحد (با حفظ آدرس اونها به جدول اصلی) و راه اندازی FTS روی این جدول هستش. از نظر سرعت هم خوب عمل میکنه