1

请耐心等待,这需要大量的前期信息来解释我想要做什么。我试图将它尽可能地通用化以使事情更清楚。在单个查询中,我希望提取与另一个表中链接的标签匹配的页面列表,并且这些标签是分组的。我希望使用项目的文本表示而不是它的 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)

此外,哪些表应该有索引,哪些索引应该用于优化?

4

1 回答 1

0

我会这样做:

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子句中,这对我来说似乎更整洁。

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

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

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

我只会索引 id 列。

真的只是我的2便士。

编辑

我在www.sqlfiddle.com上设置了一个演示。一旦我更改了列表中的别名,您的原始查询就可以正常工作。SELECT上面的尝试效果不佳:-(。我在别名方面遇到了同样的问题,一旦我修复了它们,查询就会两次返回同一行。

我从头开始重新编写它

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';

它工作正常链接

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

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

于 2013-06-03T22:11:26.230 回答