Estoy tratando con una tabla de Postgres (llamada "vidas") que contiene registros con columnas para time_stamp, usr_id, transaction_id y lives_remaining. Necesito una consulta que me dé el total más reciente de lives_remaining para cada usr_id
- Hay varios usuarios (usr_id distintos)
- time_stamp no es un identificador único: a veces, los eventos de usuario (uno por fila en la tabla) ocurrirán con el mismo time_stamp.
- trans_id es único solo para rangos de tiempo muy pequeños: con el tiempo se repite
- left_lives (para un usuario determinado) puede aumentar y disminuir con el tiempo
ejemplo:
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 necesitaré acceder a otras columnas de la fila con los datos más recientes para cada usr_id dado, necesito una consulta que dé un 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
Como se mencionó, cada usr_id puede ganar o perder vidas y, a veces, estos eventos con marca de tiempo ocurren tan cerca que tienen la misma marca de tiempo. Por lo tanto, esta consulta no 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
En su lugar, necesito usar time_stamp (primero) y trans_id (segundo) para identificar la fila correcta. Luego, también necesito pasar esa información de la subconsulta a la consulta principal que proporcionará los datos para las otras columnas de las filas apropiadas. Esta es la consulta pirateada con la que me puse a trabajar:
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
Bien, esto funciona, pero no me gusta. Requiere una consulta dentro de una consulta, una autounión, y me parece que podría ser mucho más simple tomando la fila que MAX encontró que tiene la marca de tiempo y trans_id más grandes. La tabla "vidas" tiene decenas de millones de filas para analizar, por lo que me gustaría que esta consulta fuera lo más rápida y eficiente posible. Soy nuevo en RDBM y Postgres en particular, por lo que sé que necesito hacer un uso efectivo de los índices adecuados. Estoy un poco perdido sobre cómo optimizar.
Encontré una discusión similar aquí . ¿Puedo realizar algún tipo de Postgres equivalente a una función analítica de Oracle?
Cualquier consejo sobre cómo acceder a la información de columna relacionada utilizada por una función agregada (como MAX), crear índices y crear mejores consultas sería muy apreciado.
PD: puedes usar lo siguiente para crear mi caso de ejemplo:
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);