У меня проблема с моим запросом mysql.
Моя база данных:
sections id section_name grades id user_id section_id date grade
Я хочу, чтобы мои данные показывались следующим образом:
Класс раздела
Но я хочу, чтобы оценка была самой близкой к сегодняшней дате … Это то, что у меня есть до сих пор, но она не показывает последний класс. вместо этого он заказывает id (я думаю)
SELECT * FROM grades, sections WHERE sections.id = grades.section_id AND grades.user_id = '.$id.' GROUP BY grades.section_id ORDER BY grades.date DESC
EDIT: переменная $ id является идентификатором пользователя из сеанса.
Мое решение включает использование подзапроса, чтобы получить идентификатор последнего класса, а затем передать его в запрос, который затем объединяет обе таблицы и таблицы оценок, чтобы вернуть имя_раздела и оценку. Пожалуйста, рассмотрите это как psuedocode, чем действительный sql-запрос, поскольку у меня нет времени его протестировать. Может вернуться позже, чтобы отредактировать его
SELECT section_name, grade FROM sections, grades WHERE sections.id = grades.id AND grades.id = (SELECT id FROM grades WHERE section_id = '$Id' ORDER by date DESC LIMIT 1)
Я бы предварительно запросил на основе конкретного user_id, который вы хотели, и нашел свою максимальную дату для каждого раздела. Затем повторно присоединитесь к разделам и классам (теперь, когда этот прекурсор будет чрезвычайно ограничивать набор результатов, чтобы присоединиться к нему). Затем получите название раздела и, наконец, подходящую оценку для даты, соответствующей конкретному учащемуся (пользователю), проходящему курс.
select STRAIGHT_JOIN PreQuery.Section_ID, Sections.section_name, PreQuery.LastDatePerSection from ( select section_id, user_id, max( date ) as LastDatePerSection from grades where user_id = YourUserIDParameter group by section_id ) PreQuery join sections on PreQuery.Section_ID = Sections.ID join grades on PreQuery.Section_ID = grades.Section_ID AND PreQuery.User_ID = grades.User_ID AND PreQuery.LastDatePerSection = grades.Date
SELECT sections.section_name, grades.grade FROM grades, sections WHERE sections.id = grades.section_id AND grades.user_id = '.$id.' ORDER BY grades.date DESC LIMIT 1
попробуй это?
Мне недавно приходилось делать что-то похожее, но с T-SQL, поэтому вам придется изменить его самостоятельно, чтобы заставить его работать в MySQL (которого я не установил здесь, поэтому я не могу проверить вас. Я боюсь ).
Добавить в предложение WHERE:
AND grades.date = (SELECT TOP 1 date FROM grades WHERE date > GETDATE() ORDER BY ABS(CONVERT(FLOAT,GETDATE() - date)))
GETDATE()
эквивалентен NOW()
, TOP 1
подобен LIMIT 1
и другим функциям, ну, я не знаю эквивалентов MySQL с головы!
SELECT grades.*,sections.* FROM grades inner join sections on grades.sections_id = sections.id where grades.user_id = '.$id.' GROUP BY grades.section_id ORDER BY grades.date DESC
вы можете использовать это, он работает на 100%
Если я получу это право, вы хотите получить последний класс за раздел. Это невозможно сделать просто с MySQL.
Вам понадобится функция окна или генератор последовательности, ни один из которых не доступен в MySQL. Однако есть временное решение, использующее переменные. См. Этот вопрос для аналогичного варианта использования:
Запрос MySQL: использование UNION и получение номера строки в составе SELECT
Дополнительная справочная информация здесь:
SQL / mysql – выберите отдельный / UNIQUE, но верните все столбцы?
То, что вы, скорее всего, закончите, – это большой вложенный запрос, который будет выглядеть следующим образом:
select t.* from (select @rownum := @rownum + 1 rownum, t.* from (select * from grades join sections on sections.id = grades.section_id where user_id=$id order by grades.date desc ) t, (select @rownum := 0) r ) t where t.rownum = 1
Если я правильно понимаю:
SELECT grades.*,sections.* FROM grades INNER JOIN sections ON sections.id = grades.section_id WHERE user_id=$id ORDER BY grades.date DESC LIMIT 1
Предположим, мы ищем оценки пользователей с id = 1 (просто для проверки запроса без php). Вы можете заменить его «$ Id» позже.
Если ваш столбец даты достаточно точен, чтобы убедиться, что он уникален для каждого класса, который вы можете использовать:
SELECT s.section_name, g1.grade FROM ( SELECT g.section_id, max(g.date) AS last_grade_date FROM grades g WHERE g.user_id = 1 GROUP BY g.section_id ) gd JOIN grades g1 ON g1.date = gd.last_grade_date JOIN sections s ON s.id = gd.section_id
Если ваша дата не уникальна, вам нужно присоединиться к классам обратно к себе по идентификатору, найденному в зависимом подзапросе:
SELECT s.section_name, ga.grade FROM ( SELECT g1.section_id, max(g1.date) AS last_grade_date FROM grades g1 WHERE g1.user_id = 1 GROUP BY g1.section_id ) gmax JOIN grades ga ON ga.id = ( SELECT g2.id FROM grades g2 WHERE g2.user_id = 1 AND g2.section_id = gmax.section_id AND g2.date = gmax.last_grade_date LIMIT 1 ) JOIN sections s ON s.id = gmax.section_id
Для этого запроса необходим индекс (user_id, section_id, date).
ALTER TABLE grades ADD INDEX user_section_date( user_id, section_id, date ) ;
@comment: Хорошо. Я попытаюсь объяснить второй запрос, поскольку он дает правильные результаты для любого случая.
В таблице g1 мы берем строки из оценок для пользователя с id = 1, мы группируем их по разделам, и в каждом разделе мы находим максимальную дату, что означает самую последнюю дату. На данный момент мы еще не знаем, какая строка точно содержит эту самую последнюю дату, потому что мы можем выбрать только столбцы, которые находятся в group by
или совокупным функциям (например, max ()). Mysql позволяет выбирать другие столбцы, такие как класс, называемые скрытыми столбцами (другие dbs просто бросают синтаксическую ошибку), но могут возвращать любую строку из каждой группы, обычно не та, которая нам нужна, и мы хотим, чтобы тот, Дата. Если все строки имеют одинаковое значение, например user_id, это нормально, но нам нужны оценки, которые могут быть разными в каждой группе. Для небольших таблиц выбор может возвращать правильный, поэтому некоторые люди могут требовать упорядочения по дате, могут помочь, потому что они проверяют его на небольших таблицах и видят правильные результаты, но он не соответствует правилам, когда таблица растет, появляются обновления строк, удаляются и т. Д. на.
В основном у нас есть список разделов и самых последних дат, и нам нужно узнать оценки. Поэтому нам нужно присоединиться к этой таблице g1, которую мы только что получили в таблице оценок, чтобы найти строку, которая содержит самую последнюю дату для каждого раздела. Идентификатор – единственный столбец, в котором мы уверены, что он уникален (если мы не присоединяемся к уникальному столбцу или уникальному списку столбцов, мы получим больше строк, и мы хотим точно один), поэтому мы пытаемся найти этот id в зависимом подзапросе g2 ( его подзапрос, который ссылается на значения извне, из gmax в этом случае, который является просто псевдонимом для g1, объясненным ранее).
Как только мы получим оценку для каждого section_id, осталось только присоединиться к этой таблице в section_id, чтобы получить имя_раздела вместо значения id.