mysql - 通过链接表进行多条件连接

标签 mysql

请耐心等待,这需要大量的前期信息来解释我正在尝试做的事情。我试图尽可能地通用化它以使事情更清楚。在单个查询中,我希望提取出与另一个表中链接的标签相匹配的页面列表,并且这些标签成组。我希望使用项目的文本表示而不是它的 ID,但如果没有别的,我可以做 2 个预先查询来获取 tag_id 和 taggroup_id - 只是希望不必这样做。

数据库架构:

+-----------------------------------+
| taggroups                         |
+------------------+----------------+
| taggroup_id      | group_name     |
+------------------+----------------+
| 1                | fruits         |
+------------------+----------------+

+-----------------------------------------------+
| tags                                          |
+-------------+-----------------+---------------+
| tag_id      | taggroup_id     | tag_name      |
+-------------+-----------------+---------------+
| 1           | 1               | apple         |
| 2           | 1               | orange        |
| 3           | 1               | grape         |
+-------------+-----------------+---------------+

+--------------------------------------+
| pages                                |
+------------------+-------------------+
| page_id          | title             |
+------------------+-------------------+
| 99               | Doctor a day      |
+------------------+-------------------+

+--------------------------------------------------+
| tags_to_pages                                    |
+------------+----------+---------------+----------+
| join_id    | tag_id   | taggroup_id   | page_id  |
+------------+----------+---------------+----------+
| 1          | 1        | 1             | 99       |
| 2          | 2        | 1             | 99       |
+------------+----------+---------------+----------+

测试查询: 到目前为止,似乎无法让它发挥作用。

SELECT
    pages.*, tags.tag_name, taggroups.group_name
FROM
    tags_to_pages
    INNER JOIN taggroups as grp ON (
            grp.group_name = 'fruits'
        AND
            tags_to_pages.taggroup_id = grp.taggroup_id
    )
    INNER JOIN tags as val ON (val.tag_name = 'apple' AND tags_to_pages.tag_id = val.tag_id)
    LEFT JOIN pages ON (tags_to_pages.page_id = pages.page_id)

另外,哪些表应该有索引,索引应该用来优化什么?

最佳答案

我会这样做:

SELECT
    pages.*, tags.tag_name, taggroups.group_name
FROM
    tags_to_pages
    JOIN taggroups AS grp ON grp.taggroup_id = tags_to_pages.taggroup_id
    JOIN tags AS val ON val.taggroup_id = grp.taggroup_id
    JOIN pages ON tags_to_pages.page_id = pages.page_id
WHERE
    grp.group_name='fruits'
    AND val.tag_name = 'apple'

这与您所拥有的并没有什么不同,但我将连接条件放在 JOIN 子句中,将选择条件放在 WHERE 中 子句,这对我来说似乎更整洁。

在重新输入此查询时,我发现您在某处使用了 tag_id,我认为应该是 taggroup_id,所以我更改了它,但很遗憾我现在再也看不到它了。

我还会担心选择标准 - 如果苹果不一定是水果怎么办?显然在这种情况下是这样,而且实际上是 :-),但我认为你应该只在查询中指定水果名称,而不是水果和组名称,并让数据库自行整理。

另外,为什么要对标签、tags_to_pages 和标签组使用 INNER JOIN 而对页面使用 OUTER JOIN?当然,如果没有页面,您最好不返回任何行,而不是返回一行,半满的 NULLS?

我只会索引 id 列。

只是我的 2 便士值(value),真的。

编辑

我已经在 www.sqlfiddle.com 上设置了一个演示.你的original query一旦我更改了 SELECT 列表中的别名,工作正常。我的attempt above效果不是很好:-(。我在别名方面遇到了同样的问题,一旦我修复了它们,查询就返回了同一行两次。

我从头开始重写了一遍

SELECT pages.*, tags.tag_name, taggroups.group_name
FROM pages
JOIN tags_to_pages AS ttp ON ttp.page_id = pages.page_id
JOIN tags ON tags.tag_id = ttp.tag_id
JOIN taggroups ON taggroups.taggroup_id = ttp.taggroup_id
WHERE taggroups.group_name = 'fruits' AND tags.tag_name='apple';

它工作正常 link .

设置此演示时,我突然想知道为什么要将 taggroup_id 保存在 tags_to_pages 表中。我在 SQL 和数据库方面是“自学成才”的(将其翻译为:“我边做边编,依靠做‘有效’的事情并相信直觉来找出什么是‘正确的’”)但是没有这打破了正常化的想法? tagstaggroups 之间的连接不应该只通过tags 表中的taggroup_id 列来定义吗?也许真正了解数据库的人会出现并纠正我的错误。

最后,我不知道为什么 PHPMyAdmin 在您尝试查询时挂断了。祝你好运!

关于mysql - 通过链接表进行多条件连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16906485/

相关文章:

mysql - 无法添加或更新子行

java - MySQL连接到数据库到java

mysql - 每次迭代附加到 sql 结果

mysql - 阻止用户访问管理区域

sql - MySQL 通配符 * 和 %

mysql - php排序比mysql "order by"好吗?

php - 在 GridView 列中搜索与 Yii2 中的关系

mysql - Rails ActiveRecord Mysql2::错误:未知列 'objectname.'

mysql - 我正在使用 NOT IN 但速度很慢

mysql - innodb 的 data_length 和 index_length 没有改变