MYSQL LEFT从另一个表中加入最新记录

时间:2018-09-06 13:38:07

标签: mysql left-join

我有一个training_stats表(当前应接受的培训),我也有一个completed_training表。

我想做的是查询已完成表格中最后一次完成日期的培训。

我几乎有想要的东西,我接受了应有的培训,但是它们与每个已完成的记录重复(因为每个当前到期的记录都有很多已完成的记录),我只想要单行和最新的完成日期

我一直在尝试使用MAX,当我独立运行MAX查询时,我得到了最后一条记录。但是当MAX查询处于联接状态时,它将返回所有已完成的行。

这是我正在使用的查询:

SELECT s.course_stat_id
      ,o.org_name
      ,u.id
      ,u.first_name
      ,u.last_name
      ,a.area_id
      ,a.area_name
      ,tc.course_id
      ,tc.course_name
      ,s.assigned_on
      ,s.due
      ,s.pass_mark
      ,s.completed_on
      ,completed.complete_training_id
      ,completed.complete_date
FROM training_stats s
JOIN organisations o ON o.org_id = s.org_id
LEFT JOIN (
    SELECT complete_training_id
          ,user_id
          ,area_id
          ,course_id
          ,max(completed_on) AS complete_date
    FROM completed_training
    GROUP BY complete_training_id
) completed ON completed.user_id = s.user_id
AND completed.area_id = s.area_id
AND completed.course_id = s.course_id
LEFT JOIN users u ON u.id = s.user_id
LEFT JOIN areas a ON a.area_id = s.area_id
LEFT JOIN training_courses tc ON tc.course_id = s.course_id
WHERE u.active = 1
AND o.active = 1
AND s.assigned = 1

你能看到我在做什么错吗?

2 个答案:

答案 0 :(得分:0)

我不太确定这一点。首先,运行此查询。它应该列出所有已完成的培训,其rnk从1(最新)到n(最旧)。

    SELECT complete_training_id
          ,user_id
          ,area_id
          ,course_id
          ,completed_on AS complete_date
          ,@curRank := case when complete_training_id <> @cur_complete_training_id then 0 else @curRank + 1 end rnk
    FROM completed_training, (select @curRank := 0, @cur_complete_training_id := 0)
    ORDER BY complete_training_id, completed_on DESC

如果为真,答案是:

SELECT s.course_stat_id
      ,o.org_name
      ,u.id
      ,u.first_name
      ,u.last_name
      ,a.area_id
      ,a.area_name
      ,tc.course_id
      ,tc.course_name
      ,s.assigned_on
      ,s.due
      ,s.pass_mark
      ,s.completed_on
      ,completed.complete_training_id
      ,completed.complete_date
FROM training_stats s
JOIN organisations o ON o.org_id = s.org_id
LEFT JOIN (
    SELECT complete_training_id
          ,user_id
          ,area_id
          ,course_id
          ,completed_on AS complete_date
          ,@curRank := case when complete_training_id <> @cur_complete_training_id then 0 else @curRank + 1 end rnk
    FROM completed_training, (select @curRank := 0, @cur_complete_training_id := 0)
    ORDER BY complete_training_id, completed_on DESC
) completed ON completed.user_id = s.user_id and completed.rnk = 1
AND completed.area_id = s.area_id
AND completed.course_id = s.course_id
LEFT JOIN users u ON u.id = s.user_id
LEFT JOIN areas a ON a.area_id = s.area_id
LEFT JOIN training_courses tc ON tc.course_id = s.course_id
WHERE u.active = 1
AND o.active = 1
AND s.assigned = 1

答案 1 :(得分:0)

并非完全符合您的预期结果,但是失败的原因可能是您的组by和JOIN。您的分组依据仅是培训ID,但是您也要提取用户,区域和课程以及相应的培训ID,用户,区域,课程的完成日期。您的分组方式和加入方式应符合其独特特征。

在没有看到数据的情况下,据我解释,查询是“ complete_training_id”是该表的自动增量列。话虽如此,该ID永远只有一条记录。

话虽如此,完整的培训表可以为单个用户,区域和课程提供您想要最近的多个培训日。例如,某人上大学并需要参加许多计算机课程,并且他们是以前的进修课程,因此假定所有课程都是相同的课程ID。一个人可以参加2012年,2014年,2016年。您想要显示2016年培训日期的用户/区域/课程实例。因此,让我们先来看一下。

select
      ct.user_id,
      ct.area_id,
      ct.course_id,
      max(ct.completed_on) AS complete_date
   FROM 
      completed_training ct
   GROUP BY 
      ct.user_id,
      ct.area_id,
      ct.course_id

现在,对于每个用户,每个领域和学习课程,我都有一个记录,其中包含最近的完成日期。现在让我们拉出其余的细节,但是由于您也需要完整的培训ID,因此我在下面的查询中应用了该ID。默认情况下,每次添加新记录时,ID都会增加,因此一年前完成的记录的值将比今天完成的ID低。因此,您将获得给定用户,区域,课程的完整ID及其对应的日期。

SELECT
      s.course_stat_id,
      o.org_name,
      u.id,
      u.first_name,
      u.last_name,
      a.area_id,
      a.area_name,
      tc.course_id,
      tc.course_name,
      s.assigned_on,
      s.due,
      s.pass_mark,
      s.completed_on,
      ct.complete_training_id,
      ct.complete_date
   FROM 
      training_stats s
         JOIN organisations o 
            ON s.org_id = o.org_id 
           AND o.active = 1
         LEFT JOIN 
            ( select
                    ct.user_id,
                    ct.area_id,
                    ct.course_id,
                    max(ct.complete_training_id ) as complete_training_id,
                    max(ct.completed_on) AS complete_date
                 FROM 
                    completed_training ct
                 GROUP BY 
                    ct.user_id,
                    ct.area_id,
                    ct.course_id ) ct
            on s.user_id = ct.user_id
            AND s.area_id = ct.area_id
            AND s.course_id = ct.course_id
         JOIN users u 
            ON s.user_id = u.id
            AND u.active = 1
         LEFT JOIN areas a 
            ON s.area_id = a.area_id
         LEFT JOIN training_courses tc 
            ON s.course_id = tc.course_id
   WHERE
      s.assigned = 1