#sql #postgresql
#sql #postgresql
Вопрос:
Итак, у меня есть запрос, подобный этому
select
user_id,
MAX(
case when attribute = 'one' then newValue else 'No Update' end
) as one,
MAX(
case when attribute = 'two' then newValue else 'No Update' end
) as two,
MAX(
case when attribute = 'thre' then newValue else 'No Update' end
) as thre,
from table
group by user_id
Этот запрос возвращает результат как максимальное значение для этого конкретного значения атрибута в другом столбце.
В этой таблице также есть updated_at
столбец. Теперь вместо этого я хочу, чтобы возвращаемый столбец содержал последнее значение в соответствии с этим полем updated_at.
Таким образом, в основном столбец one, two and thre
должен либо содержать последние значения в соответствии с updated_at
полем. Если там нет значений, то столбец должен содержать No Update
строку.
Что может быть правильным способом?
Пример
user_id | attribute | newValue | updatedAt
1 | one | null | 2018-01-20
1 | one | b | 2018-01-21
1 | one | a | 2018-01-22
1 | two | null | 2018-01-23
1 | two | null | 2018-01-24
1 | two | null | 2018-01-25
Итак, для приведенной выше таблицы текущий запрос вернет результат, поскольку это b
является Max
значением для attribute=one
user_id | one | two
1 | b | No Update
Но я хочу, чтобы результат столбца one
был последним в соответствии с updatedAt
таким столбцом
user_id | one | two
1 | a | No Update
Комментарии:
1. Покажите некоторые примеры данных и пример желаемых результатов.
2. Обновлено @MatBailie. Дайте мне знать, если пример неясен.
Ответ №1:
У Postgres нет функций агрегирования first и last, но вы можете получить аналогичную функциональность с помощью массивов:
select user_id,
coalesce((array_agg(newvalue order by updatedAt desc) filter (where attribute = 'one'))[1], 'No update') as one,
coalesce((array_agg(newvalue order by updatedAt desc) filter (where attribute = 'two'))[1], 'No update') as two
from t
group by user_id;
Здесь находится db<>fiddle.
Ответ №2:
Сначала используйте DISTINCT ON (user_id, attribute)
, чтобы получить только самые последние строки updatedAt
для каждой attribute
, а затем агрегируйте результаты:
select user_id,
coalesce(max(case when attribute = 'one' then newvalue end), 'No Update') one,
coalesce(max(case when attribute = 'two' then newvalue end), 'No Update') two
from (
select distinct on (user_id, attribute) *
from tablename
order by user_id, attribute, updatedAt desc
) t
group by user_id
Смотрите демонстрацию.
Результаты:
> user_id | one | two
> ------: | :-- | :--------
> 1 | a | No Update