Выберите строку MAX (последнее событие) для каждого пользователя (объединение двух таблиц с условиями) - PullRequest
0 голосов
/ 24 ноября 2018

Я новичок в Postgres и у меня возникла проблема с тем, что кажется простой задачей ... Я прочитал много примеров, и многие из них встречаются только с одной таблицей, поэтому я здесь за помощью!

У меня есть таблица пользователей и таблица событий.

Пользователи состоят из user_id, name, user_type

События состоят из event_id, user_id, event_name, event_type, event_date

Я хочу получить последние события для каждого пользователя, где user_type = full и event_type = paid

Я пробовал следующее, но Postgres говорит мне, что «ERROR: столбец« e.event_name »должен появиться в GROUP»Предложение BY или использоваться в агрегатной функции "

select 
  u.user_id, 
  u.user_type, 
  max(e.event_id), 
  e.event_name 
from 
  users u 
  join events e on u.user_id = e.user_id 
where 
  u.user_type = 'full' 
  and e.event_type = 'paid' 
group by 
  u.user_id

Примечание. В некоторых решениях упоминается DISTINCT ON, но система, которую я использую, не считает, что это допустимый SQL.

Ответы [ 2 ]

0 голосов
/ 24 ноября 2018

Наиболее эффективным методом в Postgres часто является использование distinct on:

select distinct on (u.user_id) u.user_id, u.user_type, 
       e.event_id, e.event_name 
from users u join
     events e
     on u.user_id = e.user_id 
where u.user_type = 'full' and
      e.event_type = 'paid' 
order by u.user_id, e.event_date desc;
0 голосов
/ 24 ноября 2018

Как вы уже видели, вы не можете смешивать функции строк и агрегирования таким образом.Один из распространенных подходов - использовать оконную функцию row_number для сортировки событий по дате (для каждого пользователя), а затем просто взять первые:

SELECT *
FROM   (SELECT *,
               ROW_NUMBER() OVER (PARTITION BY u.user_id ORDER BY event_date DESC) AS rn
        FROM   users u
        JOIN   events e ON u.user_id = e.user_id
        WHERE  user_type = 'full' AND
               event_type = 'paid') t
WHERE  rn = 1
...