come creare una vista mssql per ottenere le informazioni sull'ultimo stato
-
03-07-2019 - |
Domanda
diciamo, ho due tabelle, una per i record degli oggetti e una per i record delle attività su questi oggetti.
Sto inserendo un nuovo record in questa tabella di attività ogni volta che un oggetto viene inserito o aggiornato.
per dirlo in modo semplice, supponiamo che io abbia quattro campi nella tabella delle attività; objectId, tipo, stato e data.
quando un oggetto sta per essere aggiornato, sto pianificando di ottenere l'ultimo stato dell'oggetto e cercare le modifiche. se c'è una differenza tra il valore di aggiornamento e il valore precedente, imposterò il valore con un nuovo input, altrimenti lo imposterò su null. quindi ad esempio in un processo di aggiornamento, l'utente modifica solo il valore dello stato dell'oggetto ma lascia il valore del tipo uguale, quindi inserirò una nuova riga con un valore nullo per il tipo e un nuovo valore per lo stato.
SELECT * FROM Activity; oid type status date ----------------------------------------- 1 0 1 2009.03.05 17:58:07 1 null 2 2009.03.06 07:00:00 1 1 null 2009.03.07 20:18:07 1 3 null 2009.03.08 07:00:00
quindi devo creare una vista che mi dice lo stato corrente del mio oggetto come,
SELECT * FROM ObjectStateView Where oid = 1; oid type status date ----------------------------------------- 1 3 2 2009.03.08 07:00:00
come ottengo questo_?
Soluzione
Supponendo che la data possa essere utilizzata per trovare l'ultimo record:
CREATE VIEW foo
AS
SELECT
A.oid,
(SELECT TOP 1 type FROM Activity At WHERE At.OID = A.oid AND At.Date <= MAX(A.date) AND type IS NOT NULL),
(SELECT TOP 1 status FROM Activity Ast WHERE Ast.OID = A.oid AND Ast.Date <= MAX(A.date) AND status IS NOT NULL),
MAX(A.date) AS date
FROM
Activity A
GO
Modifica: se vuoi un JOIN (non testato)
CREATE VIEW foo
AS
SELECT TOP 1
A.oid,
At.type,
Ast.status,
A.date
FROM
Activity A
LEFT JOIN
(SELECT TOP 1 oid, date, type FROM Activity WHERE type IS NOT NULL ORDER BY date DESC) At ON A.OID = At.oid
LEFT JOIN
(SELECT TOP 1 oid, date, status FROM Activity WHERE status IS NOT NULL ORDER BY date DESC) Ast ON A.OID = Ast.oid
ORDER BY date DESC
GO
Avrei dovuto aggiungerlo prima:
Si ridimensionerà in modo esponenziale perché devi toccare la tabella 11 volte diverse.
Una soluzione migliore sarebbe quella di mantenere un "attuale" tabella e mantenerlo tramite un trigger sull'attività.
Altri suggerimenti
Hai preso in considerazione l'utilizzo della MAX ?
select oid, type, status, MAX(date) as max_date
from ObjectStateView
where oid = 1
Non sono proprio sicuro del motivo per cui vorresti inserire i null. Puoi tenere traccia di ciò che è cambiato tra gli input confrontando l'ultima voce con la precedente. Quindi lo stato corrente dell'oggetto è l'ultima voce nella tabella. Puoi determinare se un oggetto è cambiato creando un hash delle parti dell'oggetto su cui desideri tenere traccia delle modifiche e memorizzandolo come colonna aggiuntiva.
Valori storici:
Dato che segui le modifiche, potresti voler vedere lo stato dell'oggetto storicamente:
SELECT a.oid,
a.date,
a_type.type,
a_status.status
FROM Activity a
LEFT JOIN Activity a_type
ON a_type.oid = a.oid
AND a_type.date = (SELECT TOP 1 date FROM Activity WHERE oid = a.oid AND date <= a.date AND type IS NOT NULL ORDER BY date DESC)
LEFT JOIN Activity a_status
ON a_status.oid = a.oid
AND a_status.date = (SELECT TOP 1 date FROM Activity where oid = a.oid AND date <= a.date AND status IS NOT NULL ORDER BY date DESC)
che restituirà:
oid date type status
----------- ---------- ----------- -----------
1 2009-03-05 0 1
1 2009-03-06 0 2
1 2009-03-07 1 2
1 2009-03-08 3 2
Considerazioni sul rendimento:
D'altra parte, se hai più di un paio di campi e la tabella è grande, le prestazioni diventerebbero un problema. In questo caso avrei senso anche archiviare / memorizzare nella cache tutti i valori in un'altra tabella MyDataHistory , che conterrebbe dati come nella tabella mostrata sopra. Quindi selezionare la versione corrente (più recente) è banale usando una vista SQL che filtra l'ultima riga (solo 1 riga) per oid e data.