Как можно улучшить запрос?
Есть две таблицы
CREATE TABLE peak_sessions ( id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, begin_timestamp INTEGER NOT NULL, end_timestamp INTEGER, weight_units INTEGER DEFAULT 0, description TEXT DEFAULT "", FOREIGN KEY (user_id) REFERENCES users (id) ); |
CREATE TABLE peak_sessions ( id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, begin_timestamp INTEGER NOT NULL, end_timestamp INTEGER, weight_units INTEGER DEFAULT 0, description TEXT DEFAULT "", FOREIGN KEY (user_id) REFERENCES users (id) );
CREATE TABLE peak_sessions_sets ( id INTEGER PRIMARY KEY, session_id INTEGER NOT NULL, number INTEGER NOT NULL, begin_timestamp INTEGER NOT NULL, end_timestamp INTEGER NOT NULL, peak INTEGER NOT NULL, description TEXT DEFAULT "", measures BLOB NOT NULL, FOREIGN KEY (session_id) REFERENCES peak_sessions (id) ); |
CREATE TABLE peak_sessions_sets ( id INTEGER PRIMARY KEY, session_id INTEGER NOT NULL, number INTEGER NOT NULL, begin_timestamp INTEGER NOT NULL, end_timestamp INTEGER NOT NULL, peak INTEGER NOT NULL, description TEXT DEFAULT "", measures BLOB NOT NULL, FOREIGN KEY (session_id) REFERENCES peak_sessions (id) );
Есть peak_sessions принадлежащие конкретному user_id. Так же есть peak_sessions_sets, ссылающаяся на peak_sessions и хранящяя максимумы(peak).
Я хочу составить запрос "Среди всех peak_sessions принадлежащих пользователю peak_sessions.user_id = 1 выбрать по одной peak_sessions_sets, содержащей максимальное значение peak_sessions_sets.peak"
У меня получилось так
SELECT pss.* FROM peak_sessions_sets pss JOIN ( SELECT session_id, MAX(peak) AS max_peak FROM peak_sessions_sets JOIN peak_sessions ON peak_sessions_sets.session_id = peak_sessions.id WHERE peak_sessions.user_id = 1 GROUP BY session_id ) max_peaks ON pss.session_id = max_peaks.session_id AND pss.peak = max_peaks.max_peak; |
SELECT pss.* FROM peak_sessions_sets pss JOIN ( SELECT session_id, MAX(peak) AS max_peak FROM peak_sessions_sets JOIN peak_sessions ON peak_sessions_sets.session_id = peak_sessions.id WHERE peak_sessions.user_id = 1 GROUP BY session_id ) max_peaks ON pss.session_id = max_peaks.session_id AND pss.peak = max_peaks.max_peak;
Дополнительно:
Или ещё такой вариант
SELECT session_id, session_set_id, session_set_peak FROM peak_sessions JOIN ( SELECT session_id, peak_sessions_sets.id as session_set_id, MAX(peak) as session_set_peak FROM peak_sessions_sets JOIN peak_sessions ON peak_sessions_sets.session_id = peak_sessions.id GROUP BY session_id ) as max_peaks ON max_peaks.session_id = peak_sessions.id WHERE peak_sessions.user_id = 1 |
SELECT session_id, session_set_id, session_set_peak FROM peak_sessions JOIN ( SELECT session_id, peak_sessions_sets.id as session_set_id, MAX(peak) as session_set_peak FROM peak_sessions_sets JOIN peak_sessions ON peak_sessions_sets.session_id = peak_sessions.id GROUP BY session_id ) as max_peaks ON max_peaks.session_id = peak_sessions.id WHERE peak_sessions.user_id = 1
выбрать по одной peak_sessions_sets, содержащей максимальное значение peak_sessions_sets.peak
Это задача на having. Запрос писать лень.
Я хочу составить запрос "Среди всех peak_sessions принадлежащих пользователю peak_sessions.user_id = 1 выбрать по одной peak_sessions_sets, содержащей максимальное значение peak_sessions_sets.peak"
У меня получилось так
Запрос решает совсем другую задачу, хотя и по смыслу близкую. Если результат устраивает - переформулируйте цель, иначе - подтвердите, что запрос не решает задачу.
Ну а вообще - CTE + RANK() (или DENSE_RANK() - без разницы) в помощь.
select A.* from (SELECT Pss.session_id, Pss.peak, row_number() over (partition by Ps.id order by Pss.peak desc) rnm -- нумеруем оконной функцией выборку в пределах каждого Ps.id по нужной сортировке FROM peak_sessions_sets Pss JOIN peak_sessions Ps ON Pss.session_id = Ps.id WHERE Ps.user_id = 1 ) A where A.rnm = 1 -- извлекаем по 1 записи order by A.Peak Desc -- если надо, то еще как-то сортируем итог |
select A.* from (SELECT Pss.session_id, Pss.peak, row_number() over (partition by Ps.id order by Pss.peak desc) rnm -- нумеруем оконной функцией выборку в пределах каждого Ps.id по нужной сортировке FROM peak_sessions_sets Pss JOIN peak_sessions Ps ON Pss.session_id = Ps.id WHERE Ps.user_id = 1 ) A where A.rnm = 1 -- извлекаем по 1 записи order by A.Peak Desc -- если надо, то еще как-то сортируем итог
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для улучшения запроса можно использовать следующие подходы:
1. Уточнить вопрос: Если ваш вопрос слишком общий или не содержит достаточно информации, попробуйте добавить больше деталей. Укажите версию языка программирования, используемую операционную систему, а также другие дополнительные данные, которые могут быть полезны для тех, кто будет отвечать на ваш вопрос.
2. Предоставить минимальный рабочий пример: Часто полезно прикрепить к вопросу минимальный рабочий пример кода, который демонстрирует проблему. Это поможет другим пользователям быстрее понять суть проблемы и дать более точный ответ.
3. Поискать уже существующие ответы: Прежде чем задать вопрос, рекомендуется провести поиск по сайту, возможно, ваша проблема уже была решена другими пользователями. Это позволит избежать дублирования вопросов и ускорит получение ответа.
4. Соблюдать правила формулировки вопроса: Важно соблюдать правила формулировки вопроса на сайте, чтобы получить более качественные ответы. Укажите заголовок, соответствующий сути вопроса, и структурируйте вопрос так, чтобы он был понятен и легко читаем.
Пример использования тега
: <pre lang="php"> function helloWorld() { echo "Hello, World!"; } helloWorld();
Надеюсь, эти советы помогут вам улучшить ваш запрос и получить более качественные ответы на ваш вопрос.