Come tracciare i cambiamenti temporali in un database?

3

Immagina un software per i proprietari di teatri. È possibile accettare prenotazioni per le diverse sale del cinema. Ogni sala ha un diverso numero di posti.

Supponiamo che il proprietario voglia sapere quante persone hanno visitato il cinema ogni giorno negli anni passati. Facile, basta eseguire una query sulla tabella Prenotazioni e raggruppare per data.

Che cosa succede se vogliamo conoscere la capacità utilizzata? Quanta% di posti venduti? Semplice, partecipa alle prenotazioni con la tabella Cinema_Halls e dividi il numero di prenotazioni per il numero di posti disponibili.

Tuttavia, il 1 ° agosto, il proprietario decide di aggiungere più posti a una delle sale cinematografiche e aggiorna il database di conseguenza. Ma ora, tutte le percentuali di utilizzo prima del 1 ° agosto non sono valide, in quanto non abbiamo accesso al numero storico di posti.

Ci sono tre soluzioni che mi vengono in mente:

  1. Aggiungi una nuova tabella, che traccia il numero di posti nel tempo. Tupla: (HallID, numberOfSeats, validFrom, validUntil)
  2. Non modificare il record cinema_hall, ma aggiungine uno nuovo con un diverso numero di postazioni e contrassegna quello vecchio come non valido.
  3. Utilizza speciali funzioni di database temporali del tuo DBMS

(1) sembra essere ingombrante. Se vuoi davvero avere la possibilità di ottenere tutti i dati storici, avrai bisogno di una tabella separata per ogni singolo valore che potrebbe cambiare.

(2) non è come l'utente vorrebbe lavorare, e potrebbe introdurre effetti collaterali.

(3) potrebbe non essere supportato dal tuo sistema di database.

Quale sarebbe una buona soluzione per risolvere questo?

    
posta LTR 26.11.2014 - 10:42
fonte

3 risposte

4

Sembra che tu abbia già sollevato la domanda con la risposta:

Dal mio punto di vista, la soluzione che avrei provato è:

"... Aggiungi una nuova tabella, che tiene traccia del numero di posti nel tempo Tupla: (HallID, numberOfSeats, validFrom, validUntil) ..."

In questo modo, puoi anche monitorare quando è stato cambiato il numero di posti. Inoltre nel codice è possibile conoscere la percentuale esatta di posti venduti in ciascuna data. Non dipenderete da una funzione specifica del database (DB è un dettaglio del SW in generale).

Non sono sicuro che la marcatura della prima voce come non valida avrebbe aiutato, perché se non segui le date non sarai in grado di conoscere la capacità di una sala in un dato momento. Quindi questo annullerebbe il numero 2.

    
risposta data 26.11.2014 - 17:47
fonte
2

Non vuoi conoscere il numero totale di posti, ma il numero totale di posti disponibili per essere venduti. Ad esempio, alcuni posti possono essere fisicamente ma invendibili per un determinato evento. Sarei incline a pensare a un "posto disponibile" come una tupla di (hallId, seatId, eventId) - che puoi associare a una prenotazione quando arriva. Detto questo, puoi riassumere su un insieme di eventi, un intervallo di date (unendoti agli eventi), avere prezzi variabili, più proiezioni al giorno, ecc.

Se non desideri monitorare i singoli posti, salva solo (hallId, eventId, seatsDisponibile, seatSold) o (hallId, date, seatsDisponibile, seatSold) per ogni evento o giorno. Ci sarà potenzialmente una certa ridondanza nei dati rispetto a (1) ma renderà le query molto più pulite rispetto alla gestione degli intervalli di date.

    
risposta data 26.11.2014 - 18:27
fonte
1

Il numero della porta (2) è attraente se puoi farlo. Il problema con molte applicazioni che tracciano strutture di lunga durata (sale da concerto e altri componenti di edifici, aerei, navi da carico, ...) è che assumono che tali beni sono invarianti. Non sono. Come beni capitali relativamente inflessibili e costosi, non vengono cambiati molto spesso - ma sicuramente cambiano nel corso di tutti i loro cicli di vita, che durano da anni a decenni. I posti vengono aggiunti o rimossi, le sale sono suddivise o combinate o riassegnate radicalmente, e così via.

Se si dispone di una tabella Cinema_Halls che può registrare informazioni sull'identità (ad esempio il nome della stanza, la sua posizione nell'edificio), informazioni sul ciclo di vita (ad es. start e stop timestamp, o in database come PostgreSQL che hanno una gestione temporale leggermente migliore , un intervallo che definisce la durata del servizio), la loro capacità e / o altri parametri interessanti (ad esempio numero totale di posti, numero di posti per disabili, superficie utile in piedi quadrati, occupazione massima decretata dal Fire Marshal, ...), quindi il tuo database registra con precisione i parametri per la sala in funzione del tempo. Ha esposto un po 'più di complessità / variabilità nel tuo modello di dati, ma in modi che riflettono la realtà; fare l'utilizzo e altri join contro quella tabella di facilità sarà semplice.

Tuttavia, potresti non essere in grado di apportare modifiche dello schema così significative. In tal caso è necessario inserire i dati esternamente. L'opzione (1) è un tale approccio - in effetti, una tabella di descrizione delle strutture che presuppone che "Hall 1" è di per sé invariabile, ma che alcuni dei suoi parametri operativi variano nel tempo. Ci sono professionisti per questo approccio. Le altre tabelle, ad esempio, fanno semplicemente riferimento sempre a hallID = 1 e non è necessario che le voci 1, 4, 17, 19 e 31 siano tutte istanze diverse della "Hall 1" logica in momenti diversi. Ma le domande quando vuoi le informazioni sulla capacità di sala saranno un po 'più complesse. E se la Hall 1 è in qualche punto separata nella Hall 1A e nella Hall 1B, l'ipotesi "halls invariant" si interrompe comunque.

Se non puoi rendere Option (1) funzionante come una tabella separata, le alternative sono di codificare le informazioni sul ciclo di vita da qualche parte - ad es. stored procedure o dati statici incorporati nelle funzioni / metodi / oggetti di analisi. Questo è un approccio brutto, biforcato e un po 'fragile - ma ci sono molti casi in cui quel tipo di soluzione di nastro adesivo e cavo di colata il meglio che puoi fare, dati altri vincoli pratici / organizzativi. Nonostante i veri svantaggi dell'implementazione, il lato positivo è che il codice che richiede i valori richiesti (ad es. "Numero di posti nella sala x al tempo t") può spesso farlo in modo pulito (perché la funzione number_of_seats / metodo / procedura nasconde come viene calcolato il valore)

Il tuo suggerimento finale, la scelta (3), è ammirevole ma non fattibile, se non altro perché i database di lavoro forniscono un supporto così debole per rappresentare e calcolare relazioni temporali, proprietà e realtà. PostgreSQL ha un buon tipo di dati a intervalli . È ricco, preciso e funziona solo con PostgreSQL. Se stai usando PostgreSQL, hai a - ma è non-portatile. E un tipo di intervallo, mentre un inizio, non è quasi una capacità di "ragionamento temporale". Con altri database, stai ancora peggio. Oracle ha due tipi di intervallo, non unificati, di precisione variabile . Altri database come DB2 e MySQL supportano alcuni calcoli simili a intervalli nei loro operatori SQL e funzioni per oggetti data / ora, ma non hanno tipi di intervallo di prima classe.

Quindi, in ordine di ricchezza di soluzioni ed eleganza: opzioni 2, 1, 3.

    
risposta data 26.11.2014 - 18:53
fonte