Эффективное объединение 3 таблиц в MYSQL - PullRequest
1 голос
/ 25 февраля 2011

У меня есть 3 такие таблицы:

изображения (~ 10000 строк)

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?

Ответы [ 4 ]

2 голосов
/ 25 февраля 2011
  1. SELECT i.place_id, t.name as tag_name<br> FROM images i<br> INNER JOIN tagsToImages tti ON (tti.image_id = i.id)<br> INNER JOIN tags t ON (t.id = tti.tag_id)<br> WHERE i.place_id = 7

  2. SELECT i.filename, GROUP_CONCAT(t.name SEPARATOR ',') AS tags<br> FROM images i<br> INNER JOIN tagsToImages tti ON (tti.image_id = i.id)<br> INNER JOIN tags t ON (t.id = tti.tag_id)<br> WHERE i.place_id = 4 GROUP BY i.filename

Всегда лучше избегать множественных запросов, если это возможно.
* Имейте в виду, что максимальная длина GROUP_CONCAT контролируется переменной group_concat_max_len. Если вы ожидаете получить длинный список объединенных строк, вам может потребоваться изменить значение по умолчанию.

UPDATE
Если вы хотите, чтобы запросы отображали изображения без ассоциированных тегов, измените INNER JOIN s на LEFT JOIN s

1 голос
/ 25 февраля 2011

Простой вопрос

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'
0 голосов
/ 25 февраля 2011

выдача одного запроса с объединением лучше, чем добавление циклов, нескольких структур данных и сравнение значений вручную в PHP.

0 голосов
/ 25 февраля 2011

Для простого вопроса используйте 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/en/group-by-functions.html#function_group-concat

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...