在MYSQL中有效地连接3个表

时间:2011-02-25 18:01:13

标签: php mysql join

我有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的所有图像,并将每个图像与标签列表相关联,如下所示:

选择all with place_id = 4,同时加入标签信息。

 filename |    tags    
-----------------------
  abc.jpg | tagA       
  ghi.jpg | tagA, tagB 

通过执行多个查询在PHP中做得更好,还是可以使用MYSQL执行此操作?

4 个答案:

答案 0 :(得分:2)

  1. 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

  2. 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

  3. 如果可能的话,最好避免多次查询 *请注意GROUP_CONCAT的最大长度由group_concat_max_len变量控制。如果您希望获得一长串连接字符串,则可能需要更改默认值。

    <强>更新
    如果您希望查询显示没有相关标签的图片,请将INNER JOIN更改为LEFT JOIN s

答案 1 :(得分:1)

简单问题

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'

答案 2 :(得分:0)

对于简单的问题,请使用效率更高的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_CONCAThttp://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

答案 3 :(得分:0)

使用join发出单个查询比添加循环,多个数据结构和手动比较PHP中的值更好。