Estou lidando com uma tabela Postgres (chamada "vidas") que contém registros com colunas para time_stamp, usr_id, transaction_id e lives_remaining. Preciso de uma consulta que me dê o total de vidas_remanentes mais recentes para cada usr_id
- Existem vários usuários (usr_id's distintos)
- time_stamp não é um identificador único: às vezes os eventos do usuário (um por linha na tabela) ocorrerão com o mesmo time_stamp.
- trans_id é único apenas para intervalos de tempo muito pequenos: com o tempo, ele se repete
- restantes_vidas (para um determinado usuário) podem aumentar e diminuir ao longo do tempo
exemplo:
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
Como precisarei acessar outras colunas da linha com os dados mais recentes para cada usr_id fornecido, preciso de uma consulta que forneça um resultado como este:
time_stamp | lives_remaining | usr_id | trans_id ----------------------------------------- 11:00 | 3 | 1 | 6 10:00 | 1 | 2 | 4 13:00 | 3 | 3 | 1
Conforme mencionado, cada usr_id pode ganhar ou perder vidas e, às vezes, esses eventos com carimbo de data / hora ocorrem tão próximos que têm o mesmo carimbo de data / hora! Portanto, esta consulta não funcionará:
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
Em vez disso, preciso usar time_stamp (primeiro) e trans_id (segundo) para identificar a linha correta. Também preciso passar essas informações da subconsulta para a consulta principal que fornecerá os dados para as outras colunas das linhas apropriadas. Esta é a consulta hackeada que comecei a trabalhar:
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
Ok, isso funciona, mas eu não gosto. Requer uma consulta dentro de uma consulta, uma auto-junção, e parece-me que poderia ser muito mais simples capturando a linha que MAX descobriu ter o maior carimbo de data / hora e trans_id. A tabela "vidas" tem dezenas de milhões de linhas para analisar, então eu gostaria que essa consulta fosse o mais rápida e eficiente possível. Eu sou novo em RDBM e Postgres em particular, então eu sei que preciso fazer uso efetivo dos índices apropriados. Estou um pouco perdido em como otimizar.
Eu encontrei uma discussão semelhante aqui . Posso executar algum tipo de Postgres equivalente a uma função analítica Oracle?
Qualquer conselho sobre como acessar informações de colunas relacionadas usadas por uma função agregada (como MAX), criar índices e criar consultas melhores seria muito apreciado!
PS Você pode usar o seguinte para criar meu caso de exemplo:
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);