2013-06-03 97 views
1

忍受我,这需要大量的前期信息来解释我正在尝试做什么。我尽可能地将其尽可能通用化,以使事情更清晰。在一个查询中,我希望能够列出与另一个表中链接的标签相匹配的页面列表,并且这些标签是分组的。我希望使用该项目的文本表示,而不是它的id,但是如果没有别的,我可以做2个前置查询来获得tag_id和taggroup_id - 只是希望不必这样做。通过链接表多条件连接

DB模式:

+-----------------------------------+ 
| 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) 

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

回答

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

在重新输入此查询时,我发现您在某处我使用了tag_id,因此我改变了它,但我后悔我现在再也看不到它了。

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

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

我只索引id列。

只是我的2p值得,真的。

编辑

我已成立的这个演示上www.sqlfiddle.com。当我更改SELECT列表中的别名时,您的original query工作正常。我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

设置本演示中,它打动了我想知道为什么你在tags_to_pages表保存taggroup_id,我是“自学成才”,在SQL和数据库(那意思就是:“当我走的时候我会补上,依靠做'有用'的事情,并相信直觉找到你什么是'正确'“),但这不会打破正常化的想法吗?tagstaggroups之间的连接不应该仅通过tags表中的taggroup_id列来定义?也许有人真的理解数据库会出现,并把我的权利。

最后,我不知道为什么PHPMyAdmin只是挂起来,当你尝试你的查询。祝你好运!

+0

正如您从上述货币单位可以猜出的,我现在在英国,而且已经很晚了,所以现在我要睡觉了 - 我会在早上回复任何意见 - 即10小时。祝你好运。 – nurdglaw

+0

感谢nurd,你是否改变了查询的结构或者它的逻辑。例如。它是以不同的方式做同样的事情吗?因为我无法让我的查询摆在首位。 –

+0

爆炸 - 太慢,无法上床!我更改为在taggroupid上加入,而不是在某处添加tag_id: - |当查询“不起作用”时,你遇到了什么问题?它没有返回,还是返回“错误的东西”? – nurdglaw