#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);