У меня есть 3 таблицы:
изображения (~ 10 000 строк)
id | place_id | filename ---|----------|---------- 1 | 4 | abc.jpg 2 | 3 | def.jpg 3 | 4 | ghi.jpg 4 | 7 | jkl.jpg
теги (~ 100 строк)
id | name | ---|----------| 1 | tagA | 2 | tagB | 3 | tagC | 4 | tagD |
tagsToImages (~ 30 000 строк)
id | tag_id | image_id ---|----------|---------- 1 | 1 | 4 2 | 3 | 2 3 | 2 | 4 4 | 1 | 1
Например, последняя таблица показывает, что тег с id = 1 связан с изображением с id = 4.
У меня два вопроса, один довольно простой (я думаю!), И еще один сложный вопрос.
Простой вопрос
Учитывая place_id, как я могу перечислить все теги, у которых есть образ в этом place_id? Примером может служить:
Учитывая place_id = 7, верните tagA, tagB.
Сложный вопрос
То, что я хотел бы сделать, – это выбрать все изображения с определенным place_id и связать каждое изображение со списком таких тэгов:
Выделите все с помощью place_id = 4, присоединившись к тегам.
filename | tags ----------------------- abc.jpg | tagA ghi.jpg | tagA, tagB
Было бы лучше сделать это на PHP, выполнив несколько запросов, или я могу сделать это с помощью MYSQL?
SELECT i.place_id, t.name as tag_name
FROM images i
INNER JOIN tagsToImages tti ON (tti.image_id = i.id)
INNER JOIN tags t ON (t.id = tti.tag_id)
WHERE i.place_id = 7
SELECT i.filename, GROUP_CONCAT(t.name SEPARATOR ',') AS tags
FROM images i
INNER JOIN tagsToImages tti ON (tti.image_id = i.id)
INNER JOIN tags t ON (t.id = tti.tag_id)
WHERE i.place_id = 4 GROUP BY i.filename
Всегда лучше избегать нескольких запросов, если это возможно.
* Помните, что максимальная длина GROUP_CONCAT
контролируется переменной group_concat_max_len
. Если вы ожидаете получить длинный список конкатенированных строк, вам может потребоваться изменить значение по умолчанию.
ОБНОВИТЬ
Если вы хотите, чтобы запросы отображали изображения без привязанных тегов, измените INNER JOIN
s на LEFT JOIN
s
Простой вопрос
SELECT name FROM images RIGHT JOIN tagsToImages on images.id = tagsToImages.image_id RIGHT JOIN tags ON tags.tag_id = tagsToImages.image_id WHERE place_id = '7'
Для простого вопроса используйте join
которое будет более эффективным:
select t.name as `Tag` from images i left join tagsToImages ti on ti.image_id = i.id left join tags t on t.id = ti.tag_id where place_id = $place_id
Для жесткого вопроса см. GROUP_CONCAT
: http://dev.mysql.com/doc/refman/5.0/ru/group-by-functions.html#function_group-concat
выдача единого запроса с объединением лучше, чем добавление циклов, нескольких структур данных и ручное сравнение значений в PHP.