mysql where在列表中,但不在临时表中

1rhkuytd  于 2021-07-26  发布在  Java
关注(0)|答案(3)|浏览(307)

我正在考虑以下两个表格

|------------|  |-----------|
| user_roles |  |   roles   | 
|============|  |===========|
| user_id    |  | role_id   |
| role_id    |  | code_name |
|------------|  |-----------|

我要获取给定用户id列表中用户id所在的所有用户角色。但我想排除所有拥有代码为“特殊角色”的角色的用户。
最好的办法是什么?
举个例子,假设我有以下几点:

user_roles:             roles:

| user_id | role_id |   | role_id |  code_name   |
|=========|=========|   |=========|==============|
|    1    |    1    |   |    1    | special_role |
|    1    |    2    |   |    2    | another_role |
|    2    |    2    |   |---------|--------------|
|    3    |    2    |
|---------|---------|

我的想法是使用临时表,比如:

create temporary table if not exists all_user_ids as (
  select ur.user_id as user_id, ur.role_id as role_id
  from user_roles ur
  where ur.user_id in (1,2,3)
);

create temporary table if not exists special_user_ids as (
  select aui.user_id as user_id
  from all_user_ids aui
  join roles r on r.role_id = aui.role_id
  where r.code_name = 'special_role'
);

create temporary table if not exists non_special_user_ids as (
  select aui.user_id as user_id
  from all_user_ids aui
  where aui.user_id not in (special_user_ids.user_id)
);

最后的结果是:

select ur.user_id, ur.role_id
from user_roles ur
where ur.user_id in (non_special_user_ids.user_id)

但一定有更好的办法?!

ego6inou

ego6inou1#

您可以使用窗口函数-如果您运行的是mysql 8.0:

select *
from (
    select ur.*, r.code_name, max(r.code_name = 'special_role') over(partition by user_id) has_special_role
    from user_roles ur
    inner join roles r on r.role_id = ur.role_id
) t
where has_special_role = 0

在早期版本中,一种方法是 not exists :

select ur.*
from user_roles ur
where not exists (
    select 1 
    from user_roles ur1
    inner join roles r1 on r1.role_id = ur1.role_id
    where ur1.user_id = ur.user_id and r1.code_name = 'special_role'
)
kulphzqa

kulphzqa2#

加入吧。这应该是相当快的假设你有钥匙设置。

SELECT * FROM user_roles JOIN role ON user_roles.role_id = role.role_id 
    WHERE user_roles.user_id IN(1,2,3 ...) AND role.code_name != "special_role"

误解了提问。如果您不希望任何用户具有特殊角色:

SELECT * FROM user_roles WHERE user_id NOT IN(
    SELECT user_id FROM user_roles JOIN role ON user_role.role_id = role.role_id
        WHERE role.role_code = 'special_role')
    AND user_id IN (1, 2, 3 ...)
dsekswqp

dsekswqp3#

使用 IN 以及 NOT IN 对于两种情况:

select *
from user_roles
where user_id in (<list of usr_ids>)
and user_id not in (
  select user_id from user_roles 
  where role_id = (select role_id from roles where code_name = 'special_role')
)

请看演示。

相关问题