Pregunta

Tengo una base de datos postgres con una tabla de usuario (nombre de usuario, nombre, apellido) y una tabla de datos de usuario (nombre de usuario, código, contenido, fecha y hora de creación). Guardo información diversa sobre cada usuario en la tabla de metadatos de usuario por código y mantengo un historial completo. así, por ejemplo, un usuario (userid 15) tiene los siguientes metadatos:

15, 'QHS', '20', '2008-08-24 13:36:33.465567-04'  
15, 'QHE', '8', '2008-08-24 12:07:08.660519-04'  
15, 'QHS', '21', '2008-08-24 09:44:44.39354-04'  
15, 'QHE', '10', '2008-08-24 08:47:57.672058-04'  

Necesito obtener una lista de todos mis usuarios y el valor más reciente de cada uno de los diversos códigos de metadatos de usuario. Hice esto programáticamente y fue, por supuesto, muy lento. Lo mejor que pude encontrar para hacerlo en SQL fue unirme a las subselecciones, que también fueron lentas y tuve que hacer una para cada código.

¿Fue útil?

Solución

Supongo que no estás dispuesto a modificar tu esquema, así que me temo que mi respuesta podría no ser de mucha ayuda, pero aquí va ...

Una posible solución sería tener el campo de tiempo vacío hasta que fuera reemplazado por un valor más nuevo, cuando inserte la 'fecha de desuso' en su lugar. Otra forma es expandir la tabla con una columna 'activa', pero eso introduciría cierta redundancia.

La solución clásica sería tener los campos 'Válido desde' y 'Válido hasta' donde los campos 'Válido hasta' estén en blanco hasta que alguna otra entrada sea válida. Esto puede ser manejado fácilmente usando triggers o similar. El uso de restricciones para asegurarse de que solo haya un elemento de cada tipo que sea válido garantizará la integridad de los datos.

Común a estos es que hay una forma única de determinar el conjunto de campos actuales. Simplemente seleccionaría todas las entradas con el usuario activo y una 'Fecha de validez' o 'Fecha de desaprobación' NULL o una 'activa' verdadera.

Puede que le interese echar un vistazo a la entrada de Wikipedia en bases de datos temporales y las artículo Un glosario de consenso de conceptos de bases de datos temporales .

Otros consejos

Esto realmente no es tan difícil de hacer en PostgreSQL porque tiene el " DISTINCT ON " en su sintaxis SELECT (DISTINCT ON no es SQL estándar).

SELECT DISTINCT ON (code) code, content, createtime
FROM metatable
WHERE userid = 15
ORDER BY code, createtime DESC;

Eso limitará los resultados devueltos al primer resultado por código único, y si los clasifica por tiempo descendente de creación, obtendrá el más nuevo de cada uno.

Una subselección es la forma estándar de hacer este tipo de cosas. Solo necesita una restricción única en ID de usuario, código y fecha, y luego puede ejecutar lo siguiente:

SELECT * 
FROM Table
JOIN (
   SELECT UserId, Code, MAX(Date) as LastDate
   FROM Table
   GROUP BY UserId, Code
) as Latest ON
   Table.UserId = Latest.UserId
   AND Table.Code = Latest.Code
   AND Table.Date = Latest.Date
WHERE
   UserId = @userId
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top