Я имею дело с таблицей Postgres (называемой "жизнь" ), которая содержит записи с столбцами для time_stamp, usr_id, transaction_id и lives_remaining. Мне нужен запрос, который даст мне самую последнюю информацию о жизни, оставшуюся для каждого usr_id
- Существует несколько пользователей (разные usr_id)
- time_stamp не является уникальным идентификатором: иногда пользовательские события (по одной строке в таблице) будут встречаться с одним и тем же time_stamp.
- trans_id уникален только для очень малых диапазонов времени: со временем он повторяет
- Остальные_листы (для данного пользователя) могут со временем увеличиваться и уменьшаться
Пример:
time_stamp|lives_remaining|usr_id|trans_id ----------------------------------------- 07:00 | 1 | 1 | 1 09:00 | 4 | 2 | 2 10:00 | 2 | 3 | 3 10:00 | 1 | 2 | 4 11:00 | 4 | 1 | 5 11:00 | 3 | 1 | 6 13:00 | 3 | 3 | 1
Поскольку мне нужно будет обращаться к другим столбцам строки с последними данными для каждого заданного usr_id, мне нужен запрос, который дает результат следующим образом:
time_stamp|lives_remaining|usr_id|trans_id ----------------------------------------- 11:00 | 3 | 1 | 6 10:00 | 1 | 2 | 4 13:00 | 3 | 3 | 1
Как уже упоминалось, каждый usr_id может получать или терять жизни, а иногда эти события с временной задержкой происходят так близко друг к другу, что у них одинаковая метка времени! Поэтому этот запрос не будет работать:
SELECT b.time_stamp,b.lives_remaining,b.usr_id,b.trans_id FROM
(SELECT usr_id, max(time_stamp) AS max_timestamp
FROM lives GROUP BY usr_id ORDER BY usr_id) a
JOIN lives b ON a.max_timestamp = b.time_stamp
Вместо этого мне нужно использовать как time_stamp (first), так и trans_id (second), чтобы определить правильную строку. Затем мне также нужно передать эту информацию из подзапроса в основной запрос, который предоставит данные для других столбцов соответствующих строк. Это взломанный запрос, который я начал работать:
SELECT b.time_stamp,b.lives_remaining,b.usr_id,b.trans_id FROM
(SELECT usr_id, max(time_stamp || '*' || trans_id)
AS max_timestamp_transid
FROM lives GROUP BY usr_id ORDER BY usr_id) a
JOIN lives b ON a.max_timestamp_transid = b.time_stamp || '*' || b.trans_id
ORDER BY b.usr_id
Хорошо, так это работает, но мне это не нравится. Он требует запроса в запросе, самостоятельного присоединения, и мне кажется, что это может быть намного проще, захватив строку, которая, как установлено MAX, имеет наибольшую временную метку и trans_id. В таблице "lives" есть десятки миллионов строк для синтаксического анализа, поэтому я бы хотел, чтобы этот запрос был максимально быстрым и эффективным. Я новичок в RDBM и Postgres, поэтому я знаю, что мне нужно эффективно использовать соответствующие индексы. Я немного потерял, как оптимизировать.
Я нашел подобное обсуждение здесь. Могу ли я выполнить некоторый тип эквивалента Postgres для аналитической функции Oracle?
Любые советы по доступу к соответствующей информации о столбцах, используемой агрегированной функцией (например, MAX), созданию индексов и созданию более качественных запросов, будут высоко оценены!
P.S. Вы можете использовать следующее для создания примера для примера:
create TABLE lives (time_stamp timestamp, lives_remaining integer,
usr_id integer, trans_id integer);
insert into lives values ('2000-01-01 07:00', 1, 1, 1);
insert into lives values ('2000-01-01 09:00', 4, 2, 2);
insert into lives values ('2000-01-01 10:00', 2, 3, 3);
insert into lives values ('2000-01-01 10:00', 1, 2, 4);
insert into lives values ('2000-01-01 11:00', 4, 1, 5);
insert into lives values ('2000-01-01 11:00', 3, 1, 6);
insert into lives values ('2000-01-01 13:00', 3, 3, 1);