#sql #postgresql #datetime #inner-join #greatest-n-per-group
#sql #postgresql #дата и время #внутреннее соединение #наибольшее число пользователей на группу
Вопрос:
У меня есть эти две таблицы:
User:
=======================
id | Name | Email
=======================
1 | User-A| a@mail
2 | User-B| b@mail
=======================
Entry:
=================================================
id | agree | createdOn | userId
=================================================
1 | true | 2020-11-10 19:22:23 | 1
2 | false | 2020-11-10 22:22:23 | 1
3 | true | 2020-11-11 12:22:23 | 1
4 | true | 2020-11-04 22:22:23 | 2
5 | false | 2020-11-12 02:22:23 | 2
================================================
Мне нужно получить следующий результат:
=============================================================
Name | Email | agree | createdOn
=============================================================
User-A | a@mail | true | 2020-11-11 22:22:23
User-B | b@mail | false | 2020-11-12 02:22:23
=============================================================
Выполняемый мной запрос Postgres:
select distinct on (e."createdOn", u.id)
u.id , e.id ,u."Name" , u.email, e.agree, e."createdOn" from "user" u
inner join public.entry e on u."id" = e."userId"
order by "createdOn" desc
Но проблема в том, что он возвращает все записи после выполнения соединения! где мне нужна только самая последняя запись в createdOn
ячейке.
Комментарии:
1.
distinct on (u.id)
?
Ответ №1:
Вам нужна последняя запись для каждого пользователя. Для этого вам нужен идентификатор пользователя в distinct on
предложении, и никакой другой столбец. Это гарантирует одну строку в результирующем наборе для каждого пользователя.
Затем вам нужно поместить этот столбец первым в order by
предложении, за которым следует createdOn desc
. Это разрывает связи и решает, какая строка будет сохранена в каждой группе:
select distinct on (u.id) u.id , e.id ,u."Name" , u.email, e.agree, e."createdOn"
from "user" u
inner join public.entry e on u."id" = e."userId"
order by u.id, "createdOn" desc
Ответ №2:
Вы также можете использовать row_number для выбора последних строк, а затем выполнить объединение
SELECT * FROM USER A
LEFT JOIN (
SELECT * FROM (
SELECT *,ROW_NUMBER() OVER(PARTITION BY USERID ORDER BY CREATEDON DESC) AS RN
FROM ENTRY
) K WHERE RN = 1
) B
ON A.ID = B.USERID
Ответ №3:
Попробуйте использовать функцию createdon = max(createdon). Группировка по пользователю