mysql - 如何最好地查询 "all Y for each X that has a matching Y"的多对多关系

标签 mysql many-to-many

我有一个表,有两列,usergroup。这是一个多对多的关系,所以我们可能有...

group |  user
1     |  1
1     |  2
1     |  3
2     |  1
2     |  3
3     |  1
3     |  4
4     |  2
4     |  3

...等等。

我需要获取包含特定用户 ID 的所有组中的用户列表。所以对于上面的内容,如果我给它用户 ID 3,它会首先获取该用户的所有组(在本例中为 1、2 和 4),然后返回这些组的所有用户(在本例中为 1 、2 和 3)。现在,这是通过两个嵌套选择来完成的:

SELECT * FROM other_table
WHERE user_id IN (
    SELECT user_id FROM table WHERE group_id IN (
        SELECT group_id FROM table WHERE user_id = 3
    )
)

事实证明这是非常低效的。我在这里明显遗漏了什么吗?

即使我自己运行查询,它的运行效率也很低:

SELECT user_id FROM table WHERE group_id IN (
    SELECT group_id FROM table WHERE user_id = 3
)

编辑:这是表格的 CREATE TABLE

CREATE TABLE `user_groups` (
  `user_id` bigint(12) unsigned NOT NULL,
  `group_id` bigint(12) unsigned NOT NULL,
  PRIMARY KEY  (`user_id`,`group_id`),
  KEY `user_id` (`user_id`),
  KEY `group_id` (`group_id`),
) ENGINE=MyISAM DEFAULT CHARSET=latin1

编辑:并在下面的答案中解释查询会发生什么:

id | select_type | table | type   | possible_keys            | key      | key_len | ref         | rows | Extra
1  | SIMPLE      | t1    | ref    | PRIMARY,user_id,group_id | PRIMARY  | 8       | const       | 839  | Using index
1  | SIMPLE      | t2    | ref    | PRIMARY,user_id,group_id | group_id | 8       | t1.group_id | 2331 | 
1  | SIMPLE      | users | eq_ref | PRIMARY                  | PRIMARY  | 8       | t2.user_id  | 1    |

最佳答案

只需使用自连接:

SELECT other_table.*
FROM   `table` t1
  JOIN `table` t2 USING (group_id)
  JOIN other_table ON other_table.user_id = t2.user_id
WHERE  t1.user_id = 3

关于mysql - 如何最好地查询 "all Y for each X that has a matching Y"的多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10917838/

相关文章:

mysql - 如何组合来自两个 MySQL 表的数据以返回按一个表中的用户条目数排序的用户列表?

php - 对一列中的 group_concat 值进行排序

java - Hibernate 多对多和 JSON 序列化

c# - List<T> 项删除问题

php - 使用数据透视表访问其他表信息

mysql - 订房管理系统数据库设计

php - 多对多 Doctrine : count left join collection

sql - 如何获取多对多关系中不存在的行

mysql - SQL 多对多 JSON

mysql - 如何在 MYSQL 中使用日期创建 SUM 函数?