【问题标题】:Join 2 tables (one-to-many) and get newest entry in second table加入 2 个表(一对多)并在第二个表中获取最新条目
【发布时间】:2012-08-07 23:53:41
【问题描述】:

假设我有两个表,“users”和“audit”,并且每次用户状态更改时,触发器都会填充审计表。我正在尝试从两个表中进行选择,并获取具有关联的最新审核条目的用户条目(唯一)。假设表格具有以下字段:

用户:

  • 身份证
  • 用户名
  • 电子邮件
  • 状态

审核:

  • id(只是一个任意的自动增量)
  • user_id (fk)
  • 新状态
  • created_at(发生这种情况的日期/时间)

因此,对于每个用户条目,都有多个审核条目。

所以,最终我需要说出结果(斜体部分是审计结果,非斜体部分是 mysql 结果集中行的用户部分):
1, john, john@gmail.com, 10, 5, 1, 10, 2012-08-10-10:15:59
等等

现在,我能看到的唯一方法是进行复合选择,我在其中执行以下操作: SELECT U.*, (SELECT * FROM audit A2 where A2.id = max(A.id)) FROM users U left join audit A on (U.id = A.user_id);

问题是,如果您在用户中获得数千甚至数十万个结果,您将在数据库内部执行 n+1 次查询 - 这确实是低效的。

关于如何在不使用复合 SELECTS 的情况下将其编写为一条 SQL 语句的任何想法?

【问题讨论】:

    标签: mysql sql database


    【解决方案1】:

    我假设总是有一个相应的审计条目,因此使用了 INNER JOIN。还假设同一用户没有两个具有相同created_at 日期的审计条目。

    select u.id, u.username, u.email, u.status, 
        a.id, a.new_status, a.created_at
    from users u
    inner join (
        select user_id, max(created_at) as MaxCreated
        from audit
        group by user_id
    ) am on u.id = am.user_id
    inner join audit a on am.user_id = a.user_id and am.MaxCreated = a.created_at
    

    【讨论】:

    • 谢谢,但是如果有例如 1000 个用户,这不会导致服务器上出现 1000+1 个内部 SELECT 语句吗?它将为所有用户进行第一次选择,然后为每个用户进行一次选择以获得结果。我想要实现的是避免这种情况的选择语句。 (当然,如果可能的话,呵呵)
    • @Sarel 不,内部选择是派生表,即它将运行一次。请注意,它不是相关子查询 - 您可以自行运行子查询,它不使用其他表中的数据。然后,该派生表与usersaudit 重新连接。
    • 哇哦,太好了!谢谢伙计...这在我们的生产服务器中就像一个魅力:) 击掌
    • 这非常有帮助。根据我现在工作的代码,我认为第 8 行应该是 ) AS am on u.id = am.user_id 'AS' 不需要吗?
    • @DavidRhoden AS 是可选的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-16
    • 2017-08-17
    • 2023-03-19
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多