Я имею дело с таблицей Postgres (называемой «жизнями»), которая содержит записи со столбцами для time_stamp, usr_id, Transactions_id и Life_remaining. Мне нужен запрос, который даст мне самую последнюю итоговую сумму life_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. В таблице «live» нужно проанализировать десятки миллионов строк, поэтому я бы хотел, чтобы этот запрос был максимально быстрым и эффективным. Я новичок в 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);