在多对多关系MySql DB中,我需要选择属于列表中类别的所有资源(带标题的文档)(下例中ID为9,10的类别)。
以下是模型:
然而,这是重要的事情:对于每个资源,我想要获得资源与之关联的所有类别 - 而不仅仅是查询的... 因此,如果标题为:title_1的资源与例如id为9和10的类别匹配,但如果该资源实际上也具有类别11和12,那么我希望获得该信息。
因此,对于询问类别匹配9或10的资源的查询,我希望该资源及其所有相关类别。即,我需要这种资源的信息是:
资源标题:title_1 类别:9,10,11,12
即使我只指定它需要在查询中匹配9和10 ......
这样做的原因是,如果用户根据几个类别进行搜索,结果仍应提供有关该对象的所有关于其上设置的所有类别的信息。
到目前为止我所拥有的是:
SELECT
r.title,
cr.category_id
FROM
category_resource cr
INNER JOIN resource r
ON cr.resource_id = r.id
WHERE cr.category_id IN (9,10)
这给了我带有标记有这些资源的行的行,非常快(大约10毫秒)来自5000行的数据库。结果是3个标题:
title_1,类别:9 title_1,类别10 title_2,类别:10
即,我为title_1获得了两个结果,因为它同时包含9和10类。但我只获得这两个类别,因为它们在查询中。但这并没有给我与资源title_1相关联的其他类别。
请注意,我之前曾问过类似的问题,但并不完全。我得到了一个解决它的答案。但是它太复杂了,我需要对它进行改写,并给它一个不同的重点。关键点在于:我需要获取此信息,但它也必须与我当前更简单的查询一样快,即大约10毫秒。这可能要求很多,但与此同时,对于数据库来说,这个要求对我来说似乎并不太牵强?即获得与标准匹配的项目,并从多对多关系表中获取与in关联的所有值...
远离这方面的专家,在我看来,关键数据库应该是什么,处理关系的查询...所以我觉得必须有一个简单而有效的解决方案来解决这个问题,我只是希望我能够清楚地解释清楚......
答案 0 :(得分:1)
您可以使用Self-Join:
完成此操作这是一个有效的工作方式:http://sqlfiddle.com/#!2/1826f/6
您已加入category_resource以限制为(9,10),因此我们加入了它的副本并获得所有匹配的结果:
SELECT
r.title,
cr2.category_id
FROM
category_resource cr
INNER JOIN resource r
ON cr.resource_id = r.id
INNER JOIN category_resource cr2 on cr2.resource_id = r.id
WHERE cr.category_id IN (9,10)
GROUP BY cr2.category_id,r.title
ORDER BY r.title
根据评论进行编辑: 如果您需要所有类别(9,10),您可以将其更改为自动加入AGAIN为cr3:
SELECT
r.title,
cr2.category_id
FROM
category_resource cr
INNER JOIN resource r
ON cr.resource_id = r.id
INNER JOIN category_resource cr2 on cr2.resource_id = r.id
INNER JOIN category_resource cr3 on cr3.resource_id = r.id
WHERE cr.category_id = 9
and cr3.category_id = 10
GROUP BY cr2.category_id,r.title
ORDER BY r.title
sqlfiddle:http://sqlfiddle.com/#!2/1826f/11
或者这是使用HAVING的版本:http://sqlfiddle.com/#!2/1826f/12
SELECT
r.title,
cr2.category_id
FROM
category_resource cr
INNER JOIN resource r
ON cr.resource_id = r.id
INNER JOIN category_resource cr2 on cr2.resource_id = r.id
WHERE cr.category_id IN (9,10)
GROUP BY cr2.category_id,r.title
HAVING count(cr.category_id)=2
ORDER BY r.title
答案 1 :(得分:0)
尝试使用左连接而不是内连接。我想这可能就是你要找的东西,但我不确定我是否正确地遵循你的描述。
答案 2 :(得分:0)
好的,所以
SELECT
r.title,
cr.category_id
FROM
category_resource cr
INNER JOIN resource r
ON cr.resource_id = r.id
WHERE cr.category_id IN (9,10)
为您提供类别ID为9或10的所有资源。
如果你稍微修改一下
SELECT DISTINCT
r.title,
cr2.category_id
FROM
category_resource cr
INNER JOIN resource r
ON cr.resource_id = r.id
INNER JOIN category_resource cr2
ON cr.resource_id = cr2.resource_id
WHERE cr.category_id IN (9,10)
您应该能够获取除9和10之外的其他资源类别。
话虽如此,我不知道我完全遵循你的架构。所以让我用简单的英语解释。
修改显示具有类别9或10的所有资源的查询。 向包含每个标题/类别对的表添加另一个内连接(这是我不确定我遵循您的模式的地方)。加入标题。从包含标题/类别对的表中获取其他类别。
您可以通过在第二次使用时重复使用您将用于加入资源表的资源标题来优化此操作。但希望这会让你开始:-)