MYSQL LEFT присоединяется к последней записи из другой таблицы

У меня есть таблица 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

Вы видите, что я делаю неправильно?

Почему вы не сгруппировали свой внутренний запрос с user_id, area_id, course_id?

Ankit Bajpai 06.09.2018 16:06

Сожалею? Что ты имеешь в виду?

frobak 06.09.2018 16:07

Во внутреннем запросе поместите все столбцы в группу по предложению.

Ankit Bajpai 06.09.2018 16:07

Да, это не имело никакого значения, все еще есть повторяющиеся столбцы

frobak 06.09.2018 16:35

Какую версию MySQL вы используете? Вы можете сделать это с помощью функции ранжирования. Они новы в mysql 8, но для более старой версии можно использовать хитрость.

DanB 06.09.2018 16:53

К сожалению, я использую Mysql 5.6. Я бы подумал, что этот запрос не будет таким сложным :(

frobak 06.09.2018 17:01
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
6
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Очень признателен за вашу помощь. Я получаю эту ошибку, когда пытаюсь запустить этот запрос: # 1248 - Каждая производная таблица должна иметь собственный псевдоним

frobak 06.09.2018 17:48

добавить псевдоним после (select @curRank := 0, @cur_complete_training_id := 0)

DanB 06.09.2018 19:35
Ответ принят как подходящий

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

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

Другие вопросы по теме