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

Posted

技术标签:

【中文标题】选择多对多关系的最新记录【英文标题】:Select latest record on many to many relationship 【发布时间】:2018-09-27 03:41:06 【问题描述】:

我有一个多对多的关系,如下所示。用户可以更改他们的角色,我希望所有用户的最后一个角色等于角色 2(示例)。

用户

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_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只是选择用户的参考。

【问题讨论】:

为什么不直接选择这样的用户:SELECT user.user_id, role_id FROM users JOIN user_roles ON user.user_id = user_roles.user_id WHERE role_id = 2 GROUP BY user.user_id, role_id 很好,但是该查询将包括user1,我想选择最后一个角色= 2的用户,所以这可能包括created_at字段。提前致谢! 啊,明白了。 也许这会有所帮助?我知道我的数据库,但出于某种原因不擅长编写查询。这看起来很像你需要的东西:***.com/questions/2411559/… 您使用的是什么关系型数据库? sql 太笼统了。 【参考方案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;

编辑

根据来自 cmets 的附加信息,以下将返回 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;

【讨论】:

有效!但是我可以从users 表中选择所有数据吗?所以它可能不是select field1, field2 from user_roles,但大多像select * from users @Gregorio 我编辑的版本应该回答这个问题。 @Gregorio 如果这解决了您的问题,也许您可​​以将其标记为答案? 谢谢!我使用where in 而不是join【参考方案2】:

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;

【讨论】:

它也有效!但我需要解释一下,我也可以从users中选择所有数据,而不仅仅是从子查询中? 谢谢!我认为虽然将这个查询翻译成 laravel(至少对我来说)。我需要了解有关查询生成器的更多信息。

以上是关于选择多对多关系的最新记录的主要内容,如果未能解决你的问题,请参考以下文章

如何使用AND条件选择多对多关系中的记录[重复]

NSSortDescriptor 和多对多关系

MYSQL在一个语句中多对多选择(聊天,最新消息,用户名)

过滤多对多关系中的选择

Laravel:无法添加记录多对多关系

hibernate多对多查询