Mysql 通过链接表的多条件联接
请容忍我,这需要大量的预先信息来解释我正在尝试做什么。我已经尽可能地把它泛化,使事情更清楚。在一个查询中,我希望拉出一个与另一个表中链接的标记相匹配的页面列表,这些标记是分组的。我希望使用项目的文本表示,而不是它的id,但如果没有其他方法,我可以做2个预先查询,以获得标记id和标记组id-只是希望不必这样做 数据库模式:Mysql 通过链接表的多条件联接,mysql,Mysql,请容忍我,这需要大量的预先信息来解释我正在尝试做什么。我已经尽可能地把它泛化,使事情更清楚。在一个查询中,我希望拉出一个与另一个表中链接的标记相匹配的页面列表,这些标记是分组的。我希望使用项目的文本表示,而不是它的id,但如果没有其他方法,我可以做2个预先查询,以获得标记id和标记组id-只是希望不必这样做 数据库模式: +-----------------------------------+ | taggroups | +-----------
+-----------------------------------+
| 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
子句中,这对我来说似乎更整洁
在重新键入此查询时,我发现您在某个地方使用了标记id,我认为该标记id应该是标记组id,因此我对其进行了更改,但很抱歉现在无法再次看到它
我还担心选择标准——如果一个苹果碰巧不是水果呢?显然,在这种情况下是这样的,事实上也是这样:-),但我认为您应该只在查询中指定水果名称,而不是水果和组名称,并让数据库自己对其进行排序
另外,为什么对标记、标记到页面和标记组使用内部联接
,而对页面使用外部联接?当然,如果没有页面,您最好不返回任何行,而不是返回一行,半满为空
我只为id列编制索引
只是我的2便士,真的
编辑
我已经在上设置了一个演示。我更改了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\u id
保存在tags\u to\u pages
表中。我在SQL和数据库方面是“自学”的(将其翻译为:“我边做边补,依靠做‘工作’的事情,相信直觉来找出什么是‘正确的’)但是这不是打破了标准化的想法吗?标记
和标记组
之间的联系不应该只通过标记
表中的标记组id
列来定义吗?也许真正了解数据库的人会来纠正我
最后,我不知道为什么PHPMyAdmin在您尝试查询时挂断了电话。祝您好运!正如您可能从上面的货币单位猜到的,我在英国,时间已经很晚了,所以我现在要睡觉了-我会在上午回复任何评论-即10个小时的时间。祝您好运。谢谢nurd,您刚刚更改了查询的结构还是还有它背后的逻辑。例如,它是以不同的方式做同样的事情吗?因为我一开始无法让我的查询工作。太慢了,睡不着觉!我改为加入taggroupid而不是某个地方的tag|id:-|当查询“无法工作”时,你遇到了什么问题?它是什么也不返回,还是返回“错误的东西”?在PHPMyAdmin中,它只是坐在那里处理,没有错误,没有结果。正常查询会立即返回。也运行本地查询,因此这不是内存或大型数据库问题。非常感谢,看起来这工作得很好。您是对的,不需要额外的组id-删除它。还感谢您发现SQLFIDDLE,这是一个很棒的实用程序.