繁体   English   中英

根据外部条件从联接中仅选择一行

[英]Select only one row from a join based on foreign condition

主要思想

  • 用户hasMany角色(数据存储在表中: usersrolesuser_role
  • 我想知道用户是管理员还是客户端
  • 那么这个数据将被join ED不同的结果

我在做什么

SELECT
  `users`.`id`,
  `users`.`name`,
  `roles`.`display_name`
FROM `users`
  JOIN role_user ON users.id = role_user.user_id
  JOIN roles ON role_user.role_id = roles.id

为什么错了

因为这是我得到的结果

id       Name    Display name

1       admin    Admin
1       admin    Client
2       admin2   Admin
2       admin2   Client
3       client   Client
7       test     Admin
7       test     Client

我想要的是

id       Name   Display name

1       admin   Admin
2       admin2  Admin
3       client  Client
7       test    Admin

我如何进行这项工作

  • 以某种方式使用聚合
  • 以某种方式使用案例
  • 以某种方式联接数据的子集

谢谢您的想法!

[更新]这是一个描述问题的sqlFiddle

尝试使用以下查询:

SELECT users.`id`, users.`name`, MIN(roles.`display_name`)
FROM `users` users, `role_user` role_user, `roles` roles
WHERE users.id = role_user.user_id AND role_user.role_id = roles.id
GROUP BY users.`id`

在查询中,您联接了表,这些表为您提供了所有可能的结果组合。 该查询将仅为每个找到的userId选择role_user / roles。

编辑:添加了“分组依据”以仅选择唯一用户,而“最小”则选择了按字母顺序排列的最低角色(因此在“客户端”之前选择了“管理员”)

SELECT
      `users`.`id`,
      `users`.`name`,
      `roles`.`display_name`
FROM `users`
LEFT JOIN role_user ON users.id = role_user.user_id
left JOIN roles ON role_user.role_id = roles.id

该解决方案应该适合您:

select * from users
where users.id in (
select users.id FROM users
  JOIN role_user ON (users.id = role_user.user_id)
  JOIN roles ON (role_user.role_id = roles.id)
  where roles.display_name like 'admin'
)
Union
select * from users
where users.id not in (
select users.id FROM users
  JOIN role_user ON (users.id = role_user.user_id)
  JOIN roles ON (role_user.role_id = roles.id)
  where roles.display_name like 'admin'
);

在这里提琴: http ://sqlfiddle.com/#!9/0fabba/42

我建议为子查询创建一个视图,但是我无法在小提琴上做到这一点。

使用视图的示例:

Create or replace view admin_list as
  select users.id FROM users
  JOIN role_user ON (users.id = role_user.user_id)
  JOIN roles ON (role_user.role_id = roles.id)
  where roles.display_name like 'admin';

然后查询将非常紧凑:

select * from users
where users.id in (
  select users.id FROM admin_list
)
Union
select * from users
where users.id not in (
  select users.id FROM admin_list
);

我自己的解决方案如下

  • 创建一个视图以获取用户的角色ID(管理员或客户端)
  • 融入景观

特别是这里的视图

CREATE VIEW vw_users_role_by_priority AS (
  SELECT
    role_user.user_id,
    min(role_user.role_id) AS 'role_id'
  FROM role_user
    JOIN roles ON role_user.role_id = roles.id
  GROUP BY role_user.user_id
);

这是最后的查询

SELECT
  `users`.`id`,
  `roles`.display_name
FROM `users`
  JOIN vw_users_role_by_priority  ON vw_users_role_by_priority.user_id = users.id
  JOIN roles ON roles.id = vw_users_role_by_priority.role_id
ORDER BY `users`.`name` ASC;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM