将子查询(不在)重写为加入

Posted

技术标签:

【中文标题】将子查询(不在)重写为加入【英文标题】:Rewrite Subquery(not in) as Join 【发布时间】:2010-09-29 14:12:51 【问题描述】:

大家好,是否可以重写查询:

select userid from User where userid not in(select userid from UserRole where roleid in(8));

加入?

问题是一个用户可能有多个角色 先感谢您。

mysql> desc 用户; +--------------------+--------+------+- ----+---------+----------------+ |领域 |类型 |空 |钥匙 |默认 |额外 | +--------------------+--------+------+- ----+---------+----------------+ |用户名 |整数(11) |否 |优先级 |空 |自动增量 | |用户名 | varchar(50) |是 | |空 | |

...和其他用户相关的列

mysql> desc 用户角色; +--------+---------+------+-----+---------+------- + |领域 |类型 |空 |钥匙 |默认 |额外 | +--------+---------+------+-----+---------+------- + |用户名 |整数(11) |否 |优先级 | 0 | | |角色标识 |整数(11) |否 |优先级 | 0 | | +--------+---------+------+-----+---------+------- +

【问题讨论】:

【参考方案1】:

也许这会起作用?

select userid from User 
left outer join
(select userid, roleid from UserRole where roleid in(8)) v
on User.userid = v.userid
where roleid is null;

【讨论】:

OP想将子查询重写为join,但是这个查询还有子查询。 @ShivanRaptor: (a) OP 没有指定没有子查询只是“我可以重写为连接吗”; (b) OP 已经接受了我的回答,大概对此很满意; (c) 这一切都发生在将近 4 年前! ;-)【参考方案2】:

我认为这应该让您拥有除 8 之外的所有角色

select userid from User
where not exists 
  (select UserId from UserRole
     where UserRole.userid = User.userid and roleid not in(8) )

【讨论】:

【参考方案3】:

如果您想提高可读性,可以使用 EXCEPT 子句。

select userId from user 
except
select userId from UserRole where roleId <> 8

不确定 MySQL 是否支持“Except”。

【讨论】:

注意:MySQL 不支持EXCEPT【参考方案4】:

我没有对此进行测试,但我认为它有效。

select userID from user 
left join UserRole 
on user.userID = UserRole.userID 
and UserRole.roleID = 8
where UserRole.roleID IS NULL

【讨论】:

注:可以使用表别名

以上是关于将子查询(不在)重写为加入的主要内容,如果未能解决你的问题,请参考以下文章

将子查询的结果聚合为逗号分隔值

Oracle:如何通过将子查询删除到条件或加入同一张表来提高查询?

加入查询和子查询

将子查询转换为 JSON 性能

将子查询转换为单个查询 Hive

使用join语句加入子查询