【问题标题】:Tricky Triple Sql Join While finding the most recent dateTricky Triple Sql Join 查找最近的日期
【发布时间】:2019-05-31 13:07:20
【问题描述】:

如果之前有人以类似的方式提出过这个问题,我深表歉意。我对 SQL 相当陌生,并且很难找到解决问题的方法。很困惑。

我目前有三个表:


模板 - |编号 |姓名 |


用户 - |编号 |全名 |


更新日志 - |编号 | id_user | id_template | last_edited_at


我有一个充满模板的表格。

我有一个单独的表,其中包含对这些模板进行更改的用户。每次进行更改时,都会在更改日志表中创建一个条目。

我正在尝试创建一个查询,其主要目标是从模板中获取每条记录,以及它最近更改的时间,以及按谁。

我想出了这个查询,它可以让我找到特定模板 ID 的最新更改。

SELECT changelogs.id_user, changelogs.updated_at, users.full_name
FROM changelogs
JOIN users
ON changelogs.id_user = users.id
WHERE changelogs.id_template = :templateId
ORDER BY changelogs.updated_at DESC 
LIMIT 1

我最初尝试通过遍历每个模板记录并为每个记录 ID 运行上述查询来解决此问题,但这很慢并且不起作用。我知道在 SQL 中必须有一种方法可以做到这一点,我想看看是否有人解决了类似的问题。这个数据库不是我设计的,如果没有优化很抱歉。

我理想的最终结果应该是一个如下所示的表格:


|模板.id |模板名称 |用户名 | changelog.updated_at |

非常感谢您的任何指导

【问题讨论】:

    标签: mysql sql database greatest-n-per-group database-administration


    【解决方案1】:

    您可以使用相关子查询:

    SELECT cl.id_user, cl.updated_at, u.full_name
    FROM changelogs cl JOIN
         users u
         ON cl.id_user = u.id
    WHERE cl.updated_at = (SELECT MAX(cl2.updated_at)
                           FROM changelogs cl2
                           WHERE cl2.id_template = cl.templateId
                          );
    

    对于外部查询中引用的每个模板,子查询会找到最大更新日期。然后用于过滤外部查询中的记录。

    【讨论】:

    • 不是我,我在这个解决方案中唯一注意到的是,没有包含从未更改过的模板。如果创建不包含在 ChangeLog 表中。
    • @EdCallahan 。 . .似乎不太可能,因为接受的答案还假定所有模板都在更改日志中。
    • 我刚刚注意到我也被否决了。无论如何,您如何拒绝使用窗口函数?他们很酷。 ;)
    • @EdCallahan 无论如何都可以在 MySQL 中运行该窗口函数(使用 row_number)或类似函数,我无法运行您的查询,我想设置一个还包括模板的查询我的项目的另一部分没有更改
    【解决方案2】:

    您可以使用两个 JOIN 从所有表中获取信息,然后使用 SUBQUERY 获取 updated_at 字段的最大值,如下所示:

    SELECT 
        t.id as template_id, t.name as template_name, 
        u.name as user_name, 
        c.updated_at as changelog_updated_at 
    FROM 
        changelogs c
    
    INNER JOIN templates t on c.id_template = t.id
    INNER JOIN users u on c.id_user = u.id
    
    WHERE 
      c.updated_at = 
        (SELECT MAX(updated_at) FROM changelogs c2 where c2.id_template = t.id)
    
    ORDER BY t.template_name 
    

    【讨论】:

      【解决方案3】:

      我认为窗口函数是你的朋友。我没有启动示例表来运行它,所以我有一两种类型:

      select *
      from (
      
          select *
              ,row_number() over (partition by t.id order by c.last_edited_at desc) row
              from Templates t
              left join ChangeLog c
              on t.id=c.id_template
              left join Users u
              on c.id_user=u.id
      
      ) t
      where row=1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-10
        • 1970-01-01
        • 1970-01-01
        • 2019-06-30
        • 1970-01-01
        相关资源
        最近更新 更多