MySQL:标记功能的规范化和表连接

时间:2012-03-21 00:19:27

标签: php mysql tags

我当前的数据库结构:

     `images`            `tags`             `images_tags`
 ________________    ______________    ________________________
| id | title     |  | id | name    |  | id | image_id | tag_id |
|----|-----------|  |----|---------|  |----|----------|--------|
|  1 | Ivysaur   |  |  1 | fire    |  |  1 |     2    |    1   | Charizard: fire
|  2 | Charizard |  |  2 | flying  |  |  2 |     2    |    2   | Charizard: flying
|  3 | Squirtle  |  |  3 | water   |  |  3 |     1    |    4   |   Ivysaur: grass
|  4 | Pidgey    |  |  4 | grass   |  |  4 |     4    |    2   |    Pidgey: flying
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

我想输出带有各自值(名称)的标签。

if ($_GET["pokemon"] == "2") {
    // output Charizard's tags: fire, flying
}

但我正在努力想出一个正确的查询来做到这一点。 INNER JOIN对我来说并不熟悉,对其工作方式的解释会非常有用。

3 个答案:

答案 0 :(得分:1)

口袋妖怪。大声笑!的xD

输出标签:

SELECT t.id, t.name
FROM tags AS t 
   INNER JOIN images_tags AS r ON r.tag_id =t.id
   INNER JOIN images AS i ON r.image_id =i.id
WHERE i.id ='2'
  1. 从标签表中选择并将其别名为“t”
  2. 使用别名“r”和r.tag_id = t.id
  3. 加入第三个表(关联)
  4. 使用别名“i”和r.image_id = i.id
  5. 加入图像表
  6. 最后设置过滤器:i.id ='2'(但由于您不希望SQL注入,因此将为mysql_real_escape_string($_GET['pokemon'])
  7. 现在是一个捷径:

    if(isset($_GET['pokemon')) {
        $image_id = (int) $_GET['pokemon'];
        $r = mysql_query("SELECT t.* FROM tags t, tags_images r WHERE r.tag_id =t.id AND r.image_id ='$image_id'");
        while($tag = mysql_fetch_assoc($r)) {
            echo $tag['name'] . '<br />';
        }
    }
    

答案 1 :(得分:1)

良好的架构设计,您的查询将如下所示:

SELECT t.* 
FROM tags AS t
INNER JOIN image_tags AS it ON it.tag_id = t.id
WHERE it.image_id = 2;

Inner Join只是意味着tags表中的任何行必须在image_tags表中有相应的行。

答案 2 :(得分:1)

对于您当前的表结构:

SELECT
    tags.name
FROM tags
    LEFT JOIN image_tags ON tags.id = images_tags.tag_id
    LEFT JOIN images ON images_tags.image_id = images.id
WHERE images.id = 2

但我建议你对结构做一些改变。

  1. 摆脱image_tags.id ..这是毫无意义的。您可以从tag_id和image_id的组合创建composite primary key

  2. 停止匿名id列。人们从糟糕的教程和糟糕的ORM库中获取是无用的习惯。 tags表的ID应在tagsimage_tags表中具有相同的名称。它将使您的数据库结构更容易理解,并为查询添加一个 perk

    SELECT
        tags.name
    FROM tags
        LEFT JOIN image_tags USING(tag_id)
        LEFT JOIN images USING(image_id)
    WHERE images.image_id = 2
    
  3. 让它更容易阅读..你不觉得......

    要了解JOIN语句的工作原理,this article可能有所帮助。另外,我建议阅读SQL Antipatterns