PDA

View Full Version : حرفه ای: خوندن از دیتابیس



css-man
چهارشنبه 03 دی 1393, 01:08 صبح
دوستان این سوال هم یه چالشخوب برای برنامه نویساس هم مشکل جدید خودم

من یه جدول دارم که توش محصولات قرار میگیرن
یه جدول دیگه دارم که دسته بندی محصولات توش قرار داره

واینا با یه کلید خارجی با هم ارتباط دارن
یعنی تو جدول محصولات یه فیلد cat_id هم وجود اره که نشون میده کدوم محصول ماله کدوم دسته بندیه
حالا من میخوام با یک کوئری 9 تا محصول بیرون بکشم بطوری که از هر دسته بندی 3 تا محصول بیرون بیاد
اصلا امکانش هست؟

MMSHFE
چهارشنبه 03 دی 1393, 10:33 صبح
SET @num := 0, @type := '';
SELECT `cat_id`, `name`,
@num := if(@type = `cat_id`, @num + 1, 1) AS `row_number`,
@type := `cat_id` AS `dummy`
FROM (
SELECT * FROM `products` ORDER BY `cat_id`
) AS `temp`
GROUP BY `cat_id`, `name`
HAVING `row_number`<='3';

MMSHFE
چهارشنبه 03 دی 1393, 10:47 صبح
توضیح: دقت کنید که بطور کلی راهی برای اعمال LIMIT به هر گروه وجود نداره و بهینه ترین روشی که وجود داره، همین تعریف متغیر هست که براتون مثالش رو گذاشتم. توی کد بالا، هروقت cat_id با متغیر type@ یکی نباشه، num@ میشه 1 و اگه یکسان بودن، یکی اضافه میکنه. در نهایت فقط اون رکوردهایی میمونن که فیلد row_number اونها کمتر یا مساوی با تعداد موردنظر شما باشه. نکته مهم اینه که قبل از خوندن اطلاعات باید جدول رو برحسب فیلد cat_id مرتب کنید (کاری که توی SELECT داخلی انجام شده) وگرنه بعنوان مثال اگه بعد از cat_id با مقدار 4، رکوردی باشه که cat_id اون 1 هست، دوباره اون رکورد رو نشون میده.

css-man
پنج شنبه 04 دی 1393, 01:04 صبح
اگر میشه یه توضیح کاملتری بدید این چیزی که نوشتید من اصلا نمیدونم چی هست؟
این نوع select زدن رو اصلا ندیدم نمی فهمم چیه

MMSHFE
پنج شنبه 04 دی 1393, 11:52 صبح
اول با دستور SET دوتا متغیر تعریف میکنیم به اسامی num و type با مقادیر 0 و رشته خالی. بعد میگیم برو از جدول products که براساس cat_id مرتب کردیم، cat_id و name رو بخون و همراه اونها، توی هر رکورد متغیرهای num و type رو هم با اسامی مستعار row_number و dummy (بعنوان اسم فیلد) قرار بده و توی هر رکورد، متغیر num اگه مقدار متغیر type برابر با فیلد cat_id اون رکورد نباشه، عدد 1 میشه و اگه برابر باشه، یکی بیشتر از مقدار قبلی خودش رو میگیره و متغیر type هم مقدار فیلد cat_id رو میگیره. اینطوری بعد از هر رکورد، آخرین cat_id رو توی متغیر type داریم و براساس اون، شرط مربوط به متغیر num اجرا میشه. حالا رکوردها رو براساس فیلدهای cat_id و name گروه بندی میکنیم و درنهایت فقط رکوردهایی رو باقی میگذاریم که row_number اونها (همون متغیر num) کوچکتر یا مساوی با عدد موردنظر شماست (یعنی 3). درمورد تعریف متغیر و ساختارهای کنترلی مثل if و... توی MySQL تحقیق کنید. قدرت MySQL خیلی فراتر از یکسری SELECT و UPDATEهای ساده است و خودش یک زبان برنامه نویسی نسبتاً کامل داره.

captain_hamid
شنبه 06 دی 1393, 11:36 صبح
این دستورات mysql که نوشتین نمیشه تو php استفاده کرد؟

MMSHFE
شنبه 06 دی 1393, 11:40 صبح
اگه بخواین با PHP کار کنید اول باید دسته بندی ها رو با یک SELECT بخونید و بعد یک حلقه یکی یکی برای هرکدوم دوباره یک SELECT دیگه بزنید با LIMIT به تعداد موردنظرتون. این روش خیلی سریعتره. وقتی موتور دیتابیس قابلیتهایی داره که به شما توی کم کردن بار اسکریپت کمک میکنه، چرا استفاده نکنید؟

captain_hamid
شنبه 06 دی 1393, 11:55 صبح
خوب من با این روش که شما نوشتین آشنا نیستم. بیشتر با همون حالت معمول که کار می کنم آشنایی دارم.
حالا تو یه سند php چطوری مستقیم از این دستورات استفاده کنیم؟ باید از stored procedure استفاده کرد؟

MMSHFE
شنبه 06 دی 1393, 12:08 عصر
همین دستورات رو با mysql_query اجرا کنید و با همون روش عادی fetch کنید.

$query = <<<EOT
SET @num := 0, @type := '';
SELECT `cat_id`, `name`,
@num := if(@type = `cat_id`, @num + 1, 1) AS `row_number`,
@type := `cat_id` AS `dummy`
FROM (
SELECT * FROM `products` ORDER BY `cat_id`
) AS `temp`
GROUP BY `cat_id`, `name`
HAVING `row_number`<='3';

EOT;
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)) { ... }

css-man
دوشنبه 08 دی 1393, 22:52 عصر
ای کاش یه آموزش mysql هم آماده میکردین
خیلی مباحث هست هنوز خیلی از بچه ها بلدنیستن

MMSHFE
پنج شنبه 11 دی 1393, 08:06 صبح
اگه خدا بخواد بعد از پکیج پیشرفته سراغ MySQL میریم.