|
|
|
| Помогите, пожалуйста, может у кого-то был опыт в решении такой задачи.
Есть таблица с товарами и таблица с категориями товаров, связанная связью много-ко-многим (many-to-many) через дополнительную таблицу. То есть в каждой категории может быть несколько товаров и у каждого товара может быть несколько категорий.
goods
id | name | price
categories
id | name
goods_to_categories
good_id | category_id
Задача: вывести список товаров, показав для каждого товара, в каких категориях он находится, перечислив их через запятую.
Как это сделать одним запросом, я так и не придумал. Смог только одним запросом получить список товаров (SELECT * FROM `goods`) и потом пройти по этому списку в РНР и выполнить дополнительный запрос к базе для каждой записи, чтобы получить категории в которой эта запись находится.
Нечего и говорить, что нагрузка на сервер от такого скрипта катастрофическая - 100 записей на страницу, это 101 запрос к базе. Как можно решить такую задачу более элегантно? | |
|
|
|
|
|
|
|
для: Temnovit
(08.02.2010 в 11:25)
| | Задачу удалось решить, прошу прощения за беспокойство :)
Надеюсь кому-то поможет найденный мной ответ. Помогла функция GROUP_CONCAT, которая собирает значения, возвращая их список через запятую в виде строки.
Вот такой запрос:
SELECT
`goods`.* ,
GROUP_CONCAT( `categories`.`name` ) AS `categories`
FROM
`goods`,
`categories`,
`goods_to_categories`
WHERE
`goods`.`id` = `goods_to_categories`.`good_id` AND
`categories.`id` = `goods_to_categories`.`category_id`
GROUP BY `goods`.`id`
|
| |
|
|
|
|
|
|
|
для: Temnovit
(08.02.2010 в 12:01)
| | Вот так будет покрасивше.
SELECT
`goods`.* ,
GROUP_CONCAT( `categories`.`name` ) AS `categories`
FROM
`goods`
LEFT JOIN `goods_to_categories` ON `goods_to_categories`.`good_id` = `goods`.`id`
LEFT JOIN `categories` ON `categories.`id` = `goods_to_categories`.`category_id`
GROUP BY `goods`.`id`
|
А вот так - вообще идеально.
SELECT
`goods`.* , `cats`
FROM
`goods`
LEFT JOIN
(
SELECT
`good_id`, GROUP_CONCAT( `categories`.`name` ) AS `cats`
FROM
`goods_to_categories`
JOIN `categories` ON `categories.`id` = `goods_to_categories`.`category_id`
GROUP BY `good_id`
)AS good_cats
ON `good_cats`.`good_id` = `goods`.`id`
|
| |
|
|
|
|
|
|
|
для: Trianon
(08.02.2010 в 12:53)
| | Спасибо, в этих запросах предусмотрен вариант, когда товар не включен ни в одну категорию. | |
|
|
|
|
|
|
|
для: Trianon
(08.02.2010 в 12:53)
| | Кстати, на какие колонки стоит расставить индексы, чтобы запрос выполнялся быстро, учитывая что в каждой из таблиц 10-100 тысяч записей? Достаточно ли первичных ключей? | |
|
|
|
|
|
|
|
для: Temnovit
(09.02.2010 в 16:52)
| | на чужие ключи.
В таблице-связке - два составных ключа можно попробовать поставить.
gc(good_id , category_id)
cg(category_id, good_id)
Еще на поля ORDER BY (если требуется) | |
|
|
|