选择多对多关系的最新记录

时间:2018-04-17 08:44:44

标签: sql laravel eloquent many-to-many relationship

我有很多关系如下。用户可以更改自己的角色,我希望所有用户的最后一个角色等于role2(示例)。

用户

user_id | user_name  | user_password
1       | user1      | *hashed password*
2       | user2      | *hashed password*
3       | user3      | *hashed password*

角色

role_id | role_name | role_description
1       | role1     | *description*
2       | role2     | *description*

user_roles

user_roles_id | user_id | role_id | created_at
1             | 1       | 1       | 2018-04-10 01:01:01
2             | 2       | 2       | 2018-04-10 01:01:02
3             | 3       | 1       | 2018-04-10 01:01:03
4             | 1       | 2       | 2018-04-12 01:01:01
5             | 1       | 1       | 2018-04-13 01:01:02
6             | 2       | 1       | 2018-04-14 01:01:01
7             | 3       | 2       | 2018-04-14 01:01:02
8             | 2       | 2       | 2018-04-15 01:01:01
9             | 1       | 2       | 2018-04-15 01:01:02
10            | 1       | 1       | 2018-04-16 01:01:01

从这些表中,我想得到像

这样的东西
user_id | role_id
2       | 2
3       | 2

但是这一次我得到了

user_id | role_id
1       | 2
2       | 2
3       | 2

user1不应该在那里,因为它的最后一个角色是role1。 所以我要做的就是让用户获得最后一个角色= 2。

任何帮助将不胜感激!提前谢谢!

加成

我想要的结果是来自users表的所有数据。所以它可能就像

user_id | user_name | <and all of the rest>
2       | user2     | ...
3       | user3     | ...

所以,我上面提到的字段role_id只是选择用户的参考。

2 个答案:

答案 0 :(得分:1)

这是一个解决方案。从本质上讲,您正在查看每个用户的最新角色,如果角色为2,则仅将其包含在输出中。

SELECT 
    ur.user_id, ur.role_id 
FROM 
    user_roles ur
WHERE 
    ur.created_at = (SELECT MAX(created_at) 
                     FROM user_roles
                     WHERE user_id = ur.user_id)
    AND ur.role_id = 2
GROUP BY 
    ur.user_id, ur.role_id;

修改

根据评论中的其他信息,以下内容将返回Users表中的所有信息:

SELECT 
    u.* 
FROM
    users u INNER JOIN (
        SELECT 
            ur.user_id
        FROM 
            user_roles ur
        WHERE 
            ur.created_at = (SELECT MAX(created_at) 
                             FROM user_roles
                             WHERE user_id = ur.user_id)
            AND ur.role_id = 2
        GROUP BY 
            ur.user_id, ur.role_id) tmp ON tmp.user_id = u.user_id;

答案 1 :(得分:1)

使用subquery相关方法并执行joins

select u.user_id, u.user_name, u.user_password, 
       r.role_id, r.role_name,  r.role_description
from (select  t.user_id, (select role_id from user_roles 
                          where user_id = t.user_id
                          order by created_at desc LIMIT 1) as role_id
      from user_roles t
      group by t.user_id) tt
inner join users u on u.user_id  = tt.user_id
inner join roles r on r.role_id = tt.role_id 
where r.role_id <> 1;