#sql #postgresql
#sql #postgresql
Вопрос:
У меня есть простая таблица с идентификатором unit_id oid, меткой времени time, diag bytea. Первичный ключ представляет собой комбинацию как time, так и unit_id.
Идея этого запроса состоит в том, чтобы получить последнюю строку (наибольшую временную метку) для каждого уникального идентификатора unit_id. Однако строки для каждого unit_id с последним временем не всегда возвращаются.
Я действительно хочу группировать только по идентификатору unit_id, но postgres заставляет меня также использовать diag, поскольку я выбираю это.
SELECT DISTINCT ON(unit_id) max(time) as time, diag, unit_id
FROM diagnostics.unit_diag_history
GROUP BY unit_id, diag
Ответ №1:
Каждый раз, когда вы начинаете думать, что вам нужна локализованная ГРУППА, вам следует начать думать о функциях окна.
Я думаю, вам нужно что-то вроде этого:
select unit_id, time, diag
from (
select unit_id, time, diag,
rank() over (partition by unit_id order by time desc) as rank
from diagnostics.unit_diag_history
) as dt
where rank = 1
Возможно, вы захотите добавить что-то в ORDER BY, чтобы также последовательно разрывать связи, но это не изменит общую технику.
Комментарии:
1. Можем ли мы сделать это без использования sub select ?
2. @metdos: я ничего не могу придумать, но может быть способ. Что не так с производными таблицами?
Ответ №2:
Вы можете объединить сгруппированный выбор с исходной таблицей:
SELECT d.time, d.diag, d.unit_id
FROM(
SELECT unit_id, max(time) as max_time
FROM diagnostics.unit_diag_history
GROUP BY unit_id
) s JOIN diagnostics.unit_diag_history d
ON s.unit_id = d.unit_id AND s.max_time = d.time
Комментарии:
1. Это единственный ответ, который я нашел за несколько дней поиска в Google, который мне каким-либо образом помог (исходя из MySQL).
2. Очень старый комментарий, но все еще очень полезный 🙂