MYSQL LEFT СОЕДИНЕНИЕ последней записи из другой таблицы - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть таблица training_stats (текущее обучение), а также таблица завершения_обучения.

То, что я хочу сделать, это запросить обучение с последней завершенной датой из заполненной таблицы.

Я почти получил то, что хочу, я получил необходимое обучение, но они дублируются с каждой завершенной записью (так как на каждую текущую запись приходится много завершенных записей), и мне нужны только отдельные строки и последняя завершенная дата .

Я пытался использовать 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 голосов
/ 06 сентября 2018

Не совсем положительный результат ваших ожидаемых результатов, но сбой, вероятно, для вашей группы и ПРИСОЕДИНЯЙТЕСЬ. Ваша группа указана ТОЛЬКО по идентификатору обучения, но вы также указываете пользователя, область и курс, а также максимальную дату, указанную для указанного соответствующего идентификатора обучения, пользователя, области, курса. Ваша группировка и присоединение должны соответствовать уникальным характеристикам.

Не видя данных, запрос, как я понимаю, состоит в том, что "complete_training_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

Теперь для каждого пользователя, области и курса обучения у меня есть одна запись с самой последней датой завершения. СЕЙЧАС давайте потянем остальные детали, но так как вам также нужен завершенный идентификатор обучения, я применил 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,
      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
0 голосов
/ 06 сентября 2018

Я не уверен на 100% в этом. Сначала запустите этот запрос. В нем должен быть указан весь пройденный курс обучения, начиная с 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
...