Domanda

Ho un database Postgres con una tabella utente (ID utente, nome, cognome) e una tabella usermetadata (ID utente, codice, contenuto, data/ora creata).Memorizzo varie informazioni su ciascun utente nella tabella dei metadati utente per codice e conservo una cronologia completa.quindi, ad esempio, un utente (userid 15) ha i seguenti metadati:

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'  

Devo recuperare un elenco di tutti i miei utenti e il valore più recente di ciascuno dei vari codici di metadati utente.L'ho fatto a livello di programmazione ed è stato, ovviamente, terribilmente lento.La cosa migliore che sono riuscito a trovare per farlo in SQL è stato unire le sottoselezione, anch'esse lente e dovevo farne una per ciascun codice.

È stato utile?

Soluzione

Suppongo che tu non sia disposto a modificare il tuo schema, quindi temo che la mia risposta potrebbe non essere di grande aiuto, ma ecco qui...

Una possibile soluzione potrebbe essere quella di lasciare vuoto il campo dell'ora finché non viene sostituito da un valore più recente, quando si inserisce invece la "data di deprecazione".Un altro modo è espandere la tabella con una colonna "attiva", ma ciò introdurrebbe una certa ridondanza.

La soluzione classica sarebbe quella di avere entrambi i campi "Valido-Da" e "Valido-Per" in cui i campi "Valido-Per" sono vuoti finché qualche altra voce non diventa valida.Questo può essere gestito facilmente utilizzando trigger o simili.L'utilizzo dei vincoli per assicurarsi che sia valido un solo elemento di ciascun tipo garantirà l'integrità dei dati.

Comune a questi è che esiste un unico modo per determinare l'insieme dei campi correnti.Dovresti semplicemente selezionare tutte le voci con l'utente attivo e un "Valido per" o una "data di deprecazione" NULL o un vero "attivo".

Potrebbe interessarti dare un'occhiata alla voce di Wikipedia su database temporali e l'articolo Un glossario consensuale dei concetti di database temporale.

Altri suggerimenti

In realtà questo non è così difficile da fare in PostgreSQL perché ha il file "DISTINTO SU" clausola nella sua sintassi SELECT (DISTINCT ON non è SQL standard).

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

Ciò limiterà i risultati restituiti al primo risultato per codice univoco e, se ordini i risultati in base all'ora di creazione decrescente, otterrai il più recente di ciascuno.

Una sottoselezione è il modo standard per fare questo genere di cose.Hai solo bisogno di un vincolo univoco su ID utente, codice e data, quindi puoi eseguire quanto segue:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top