MySQL:多对多如何获得所有(相关)类别&结合查询

时间:2012-01-22 22:13:41

标签: mysql join many-to-many

表格:

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

查询我喜欢的结果的最有效方法是什么。是否有更高效(更好的预成型)解决方案?   我应该使用一个而不是两个查询吗?

3 个答案:

答案 0 :(得分:2)

SELECT DISTINCT
        x1.category
    FROM 
        many_to_many e1           
    INNER JOIN
        many_to_many x1 
      ON e1.id = x1.id
    WHERE
        e1.category = 3          --- IN (3) 
      AND
        x1.category <> 3         --- NOT IN (3)

您应该使用EXPLAIN检查查询计划。 (category, id)上的复合索引可能适用于此查询。

答案 1 :(得分:1)

也许这个?

SELECT DISTINCT e2.category
FROM many_to_many e1, many_to_many e2
WHERE
    e1.category='3'
    AND e1.id=e2.id

这将使用该表两次,使所有类别包含具有类别“3”的ID。这也会返回类别“3”,如果您愿意,可以将其排除。

答案 2 :(得分:1)

首先,您的第二个查询(包含类别3的所有ID)不需要加入x1(请注意您根本不使用它):

SELECT DISTINCT
    e1.id
FROM 
    many_to_many e1           
WHERE
    e1.category IN (3)

然后您的第一个查询可以简化:

SELECT DISTINCT
    category
FROM 
    many_to_many e1     
WHERE id IN 
    (
    SELECT DISTINCT
        e1.id
    FROM 
        many_to_many e1           
    WHERE
        e1.category IN (3)
    )

解决方案

然而而不是使用子查询,您只需加入,这通常比子查询更有效:

SELECT DISTINCT e2.category 
FROM many_to_many e1 
LEFT JOIN many_to_many e2 ON e1.id=e2.id 
WHERE e1.category IN (3);

这会在many_to_many上将id加入自身,形成每个id的所有类别组合。特别是,对于出现在同一(3,i)中的所有其他类别i,将有一行id

如果您不想包含3,请将LEFT JOIN更改为:

LEFT JOIN many_to_may e2 ON e1.id=e2.id AND e1.category<>e2.category