Объединить два запроса вместе

#mysql #sql #inner-join

#mysql #sql #внутреннее объединение

Вопрос:

У меня есть база данных, которая содержит кучу информации об учениках в следующих таблицах

 Student:
    id
    created_on
    updated_on

StudentHistory
    id
    studentid
    schoolid
    gradeid
    datestamp
    active
  

История учащихся управляет тем, как учащиеся меняются с годами, и позволяет мне сообщать о росте числа учащихся.

Теперь мне нужно выполнить следующий запрос:

 SELECT * FROM students
INNER JOIN studenthistory
    ON student.id = studenthistory.studentid
WHERE studenthistory.active = 1
  

Проблема в том, что запрос не обязательно извлекает последнюю запись истории, как мне нужно. Есть ли способ, которым я могу гарантировать, что при объединении будет извлечена только последняя запись истории?

Комментарии:

1. как насчет добавления «упорядочить по datestamp desc» и получения первой строки

2. Этого недостаточно, он, вероятно, хочет самую последнюю историю для каждого студента

3. Я действительно хотел самую последнюю историю для каждого студента.

Ответ №1:

 SELECT  *
FROM    students s
JOIN    studentshistory sh
ON      sh.id =
        (
        SELECT  shi.id
        FROM    studentshistory shi
        WHERE   shi.studentid = s.id
                AND shi.active = 1
        ORDER BY
                studentid DESC, active DESC, datestamp DESC, id DESC
        LIMIT 1
        )
  

Создайте индекс на studentshistory (studentid, active, datestamp, id) , чтобы это работало быстро.

Комментарии:

1. Вам не нужно выполнять сортировку по идентификатору studentid, или active, или id.

2. @Frits: сортировка по studentid, active позволит MySQL правильно использовать индекс. Сортировка по id позволит избавиться от дубликатов. Было ли это причиной вашего снижения?

3. Какой индекс? Вам не нужен индекс. Не стоит чрезмерно усложнять ситуацию.

4. @Frits: просто для пояснения: это не форум, это сайт вопросов и ответов. Обычно лучший способ убедить — написать свой собственный ответ.

5. @Conrad: а, тогда не стесняйтесь взглянуть на at 🙂 С помощью LEFT JOIN он также вернет пользователей без активных записей истории.

Ответ №2:

Я думаю, это должно сработать:

 SELECT * FROM Students
INNER JOIN StudentHistory sh1 
  ON Student.studentid = sh1.studentid 
  AND StudentHistory.datestamp = 
    (SELECT MAX(datestamp) 
     FROM StudentHistory sh2 
     WHERE sh2.studentid = sh1.studentid);