请耐心等待,这需要大量的前期信息来解释我正在尝试做的事情。我试图尽可能地通用化它以使事情更清楚。在单个查询中,我希望提取出与另一个表中链接的标签相匹配的页面列表,并且这些标签成组。我希望使用项目的文本表示而不是它的 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 和数据库方面是“自学成才”的(将其翻译为:“我边做边编,依靠做‘有效’的事情并相信直觉来找出什么是‘正确的’”)但是没有这打破了正常化的想法? tags
和taggroups
之间的连接不应该只通过tags
表中的taggroup_id
列来定义吗?也许真正了解数据库的人会出现并纠正我的错误。
最后,我不知道为什么 PHPMyAdmin 在您尝试查询时挂断了。祝你好运!
关于mysql - 通过链接表进行多条件连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16906485/