LINUX.ORG.RU

выборка актуальных по дате данных

 ,


0

1

Имеется табличка, в которой тип группы меняется с течением времени:

select * from user_groups_by_types ;
 id | change_date | user_group | group_type 
----+-------------+------------+------------
  1 | 2022-05-01  | A          | type1
  2 | 2022-05-05  | A          | type2
  3 | 2022-05-06  | B          | type1

Требуется выбрать для каждой группы актуальный тип (т.е. самый последний по дате тип). Решение для одной конкретной группы очевидно. Как это обобщить на все группы?

select * from user_groups_by_types where user_group = 'A' and change_date = (select max(change_date) from user_groups_by_types where user_group = 'A');
 id | change_date | user_group | group_type 
----+-------------+------------+------------
  2 | 2022-05-05  | A          | type2

У вас структура говна, ибо из конкретной записи не возможно узнать дату когда тип станет неактуальным.
По-нормальному делаются 2 даты - начальная и конечная. В таком случае всё выбирается банальным between, да и вообще, это удобнее в большинстве других кейсов.

crutch_master ★★★★★
()
Ответ на: комментарий от scisearcher

структура мне дана и менять ее нельзя, к сожалению

Печально. Но если было бы можно приделать таблицу сбоку я бы приделал. А так изъёжам не будет конца.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 2)
Ответ на: комментарий от scisearcher

Значит надо приводить к нормальному виду и добавлять недостающие данные заджоинив таблицу саму с собой по следующей-предыдущей записи, что то еще удовольствие.
Хотя в конкретном случае можно просто приджоинить

select max(change_date) from user_groups_by_types group by user_group
по этой самой user_group и стравнить по change_date.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от crutch_master

Спасибо за идею. Кстати, можно проще. Добавить столбец is_active и при назначении нового типа заполнять этот столбец в 1-й или 2-х записях. Хотя start_date и end_date более универсально. Но, править БД незя, c distinct group by выкрутился )

scisearcher
() автор топика
21 октября 2022 г.

Во-первых решение для одной группы есть и лучше - без подзапроса:

SELECT *
FROM user_groups_by_types
WHERE user_group='A'
ORDER BY change_date DESC
LIMIT 1
Во-вторых для всех групп оно тоже очевидное, но не слишком быстрое и читаемое (которое предложил crutch_master):
SELECT t1.id, t1.change_date, t1.user_group, t1.group_type
FROM user_groups_by_types t1 INNER JOIN
(SELECT MAX(change_date) AS max_date, user_group FROM user_groups_by_types GROUP BY user_group) t2
ON t1.change_date=t2.max_date AND t1.user_group=t2.user_group
Чтобы сделать хорошо, можно сделать так (но для этого придется поменять структуру):
Добавить в таблицу булев столбец is_current
SELECT *
FROM user_groups_by_types
WHERE is_current=TRUE
Вообще это гуглится slowly changing dimension.

damix9 ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.