根据外来条件从连接中仅选择一行

时间:2017-09-11 09:28:46

标签: mysql join

主要想法

  • 用户hasMany个角色(数据存储在表格中:usersrolesuser_role
  • 我想知道用户是否是管理员或客户
  • 此数据将join添加到其他结果

我正在做什么

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

4 个答案:

答案 0 :(得分:0)

尝试使用此查询:

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。

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

此解决方案应该适合您:

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
);

答案 3 :(得分:0)

我自己的解决方案如下

  • 创建一个视图以获取用户的角色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;