MySQL:多对多如何获取所有(相关)类别和类别组合查询
表:
id | category (there is a index on id & category)
-----------
1 | 1
1 | 7
1 | 3
2 | 1
2 | 2
2 | 4
3 | 1
3 | 6
3 | 3
SELECT DISTINCT
category
FROM
many_to_many e1
WHERE id IN
(
SELECT DISTINCT
e1.id
FROM
many_to_many e1
INNER JOIN
many_to_many x1
ON e1.id=x1.id
WHERE
e1.category IN (3)
)
我喜欢返回:** 6, 1, 7**(我通过上面的查询得到的结果)
在我看来,这个查询没有很好地执行,因为子查询搜索所有 ID,并且这个列表可能很大。
另外,数量并不重要,只要 ID 相关即可。
因此,对于性能而言,如果对要填充的每个唯一类别检查一次 100 个 id 就足够了。
其次,我使用另一个查询(子查询)来获取包含该类别的所有 id:
SELECT DISTINCT
e1.id
FROM
many_to_many e1
INNER JOIN
many_to_many x1
ON e1.id=x1.id
WHERE
e1.category IN (3)
returns: 3 & 1
查询我喜欢的结果的最有效方法是什么。是否有更有效(更好的预成型)的解决方案?
我应该使用一个而不是两个查询吗?
The table:
id | category (there is a index on id & category)
-----------
1 | 1
1 | 7
1 | 3
2 | 1
2 | 2
2 | 4
3 | 1
3 | 6
3 | 3
SELECT DISTINCT
category
FROM
many_to_many e1
WHERE id IN
(
SELECT DISTINCT
e1.id
FROM
many_to_many e1
INNER JOIN
many_to_many x1
ON e1.id=x1.id
WHERE
e1.category IN (3)
)
I like to get retured: ** 6, 1, 7** (what I do get with the query above)
It seems to me this query is not gone preform well, because the sub query searches all the ID's and this list can be huge.
Also it doesn't matter how many but if the ID is related.
So for performance if there would be 100 id's checking once for each unique category to be populated would be enough.
Secondly I use an other query (the sub query )the get all id's who contain the category:
SELECT DISTINCT
e1.id
FROM
many_to_many e1
INNER JOIN
many_to_many x1
ON e1.id=x1.id
WHERE
e1.category IN (3)
returns: 3 & 1
What would be the most efficient way to query the result I like. Is there an more efficient (better preforming) solution?
Should I use one instead of two query's?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该使用 EXPLAIN 检查查询计划。
(category, id)
上的复合索引可能适合此查询。You shouldl check the plan of the query with EXPLAIN. A compound index on
(category, id)
might be good for this query.也许是这个?
这会使用该表两次,获取包含类别为“3”的 ID 的所有类别。这还会返回类别“3”,如果您愿意,可以将其排除。
Perhaps this?
This uses the table twice, getting all categories containing an ID which has category '3'. This also returns category '3', which you may exclude if you like.
首先,您的第二个查询(包含类别 3 的所有 id)不需要连接到
x1
(注意您根本不使用它):然后您的第一个查询可以简化:
解决方案
<然而,您可以不使用子查询而直接连接,这通常比子查询更有效:
这将
many_to_many
连接到id
上的自身形成类别的所有组合每个id
。特别是,同一id
中出现的所有其他类别i
都会有一行(3,i)
。如果您不想包含 3,请将
LEFT JOIN
更改为:First your second query (all id's that contain category 3) doesn't require the join to
x1
(notice how you don't use it at all):Then your first query can be simplified:
Solution
However instead of using a subquery you can just join, which is usually more efficient than a sub-query:
This joins
many_to_many
to itself onid
which forms all combinations of categories for eachid
. In particular, there will be a row(3,i)
for all other categoriesi
that appear in the sameid
.If you don't want 3 to be included, change the
LEFT JOIN
to: