Il modo migliore per archiviare le unità nel database


21

Ho ereditato un grande database (SQLServer) con centinaia di colonne che rappresentano quantità di una cosa o l'altra. Le unità per questi valori (ad es. "Galloni", "pollici", ecc.) Sono memorizzate nel campo MS_Description di Proprietà estese. Mi chiedo se esiste un modo migliore per conservare queste informazioni. Suppongo che vada bene ai fini della documentazione, ma sarebbe difficile effettuare calcoli di conversione di unità robusti basati su questi dati. A questo punto non sono disposto a fare un cambiamento invasivo, ma se ne avrò la possibilità, qual è la migliore pratica raccomandata in tal senso? Le opzioni, nella parte superiore della mia testa, potrebbero includere:

  • Cambia il nome della colonna in unità incluse (ad es. "TotalVolumeInGallons". Ciò renderebbe le informazioni un po 'più facilmente disponibili, ma mi sembra comunque debole.)
  • Aggiungi una colonna "Unità" separata per corrispondere a ogni colonna "Quantità" (questa colonna potrebbe essere nvarchar O potrebbe essere una chiave esterna in una tabella Unità separata che potrebbe facilitare il calcolo delle conversioni di unità. D'altra parte, aggiungendo così molte colonne potrebbero raddoppiare le dimensioni del mio database, con dati terribilmente ridondanti.)
  • Crea un nuovo campo in Proprietà estese dedicato specificamente alle unità. (Sfortunatamente, non penso che questa possa essere una chiave esterna per una tabella Unità.)
  • C'è un'altra idea che sto trascurando?

AGGIORNAMENTO: Dopo aver letto la risposta di @Todd Everett, mi è venuta in mente una possibile soluzione, quindi vado avanti e rispondo alla mia domanda. (Vedi sotto)


La migliore pratica è di avere un unico sistema di misurazione utilizzato universalmente e coerentemente in tutta l'applicazione. SI sarebbe il sistema di scelta. I valori in altri sistemi verranno convertiti durante il caricamento o nel livello di presentazione, in cui ciascun utente può scegliere il proprio set preferito.
Michael Green,

Risposte:


12

Dato che menzioni centinaia di colonne, prenderei in considerazione un progetto EAV . Mentre Joe Celko mette in guardia contro questo , penso che potrebbe essere applicabile nel tuo caso d'uso. Sembra che tutti i tuoi "importi" siano numeri, quindi eviterai i problemi di casting descritti da Joe e la necessità di trasformare ogni "valore" in una stringa. Funzionerà ancora meglio se tutti gli importi sono numeri interi, ma può funzionare anche se alcuni sono decimali. Date le Unità di misura, è possibile fare un ulteriore passo avanti e implementare un modello di stile "modello dati universale" basato su questo articolo di David Hay e delineato anche nel suo libro Modelli di modelli di dati: Convenzioni del pensiero. Questo modello ha l'ulteriore vantaggio di configurare quali "importi" si applicano a quali "cose" se ne hai bisogno. Un ulteriore passaggio mostrato nel libro a pagina 162 è una tabella di conversione delle unità di misura che è possibile utilizzare per convertire tra le diverse unità di misura. Ecco un esempio:

UOM Conversion              

UOM From    UOM To        Cal Step  Operator Factor Constant
Kilograms   Pounds        1         *        2.2
Celsius     Fahrenheit    1         *        1.8
Celsius     Fahrenheit    2         +               32

Ciò significa che per convertire da Kg a Lb il primo passo è moltiplicare Kg per 2,2. Esiste anche una costante se una conversione deve includere anche un valore costante e la possibilità di creare più passaggi. Quindi, quando si esegue la conversione, dire Celsius in Fahrenheit si moltiplica Celsius per 1,8 e quindi si aggiunge 32. La chiave sarebbe da UOM, a UOM e al passo di calcolo.

Questo è il mio valore di 2 centesimi. Spero che questi riferimenti ti diano un buon spunto di riflessione se dovessi mai avere la possibilità di fare un riavvio sul design attuale.


Grazie per alcuni spunti di riflessione molto interessanti - ho imparato molto. Tuttavia, non credo che EAV sia il modello appropriato nel mio caso (se capisco correttamente il tuo suggerimento) perché, sebbene abbiamo centinaia di colonne, non sono affatto sparse. Tuttavia, questo DID ha suscitato un'idea correlata (vedi AGGIORNAMENTO nel mio post originale).
kmote

La tua idea suona piuttosto bene per me - non riesco a pensare fuori mano a qualsiasi problema con esso diverso da quello che hai già sottolineato. Ma se le colonne possono essere rinominate / modificate, ciò costituirebbe un problema in qualsiasi progetto. Questo è quando la collaborazione è divertente - emerge un'idea che nessuno di noi ha pensato di iniziare!
Todd Everett,

8

Tutto il lavoro.

Nel secondo caso, non è possibile aggiungere mele e arance, quindi i dati sono eccezionalmente facili da sottoporre a interpretazioni errate.

Inoltre, le conversioni non possono essere molto sicure e sono suscettibili di errori di arrotondamento, overflow, ecc.

Inoltre, ci sono problemi fisici come il peso e la temperatura specifici. Convertire 20 litri d'acqua in libbre richiederebbe di conoscere la densità dell'acqua. Ma la densità dell'acqua cambia con la temperatura, quindi potrebbe essere necessario conoscere la densità contemporaneamente alla misurazione o la temperatura in modo simile e utilizzare un fattore di correzione del volume.

Nel caso delle proprietà estese, va bene solo per la documentazione: un buon nome di colonna è migliore per la documentazione. Il problema con la colonna implica che si trova in un'unità fissa per nome è che finisci per metterti in un angolo quando cambi unità di misura - il nuovo cliente vuole petrolio in barili e non galloni - e questo andrebbe bene poiché i loro dati sono in il proprio database, ma il nome della colonna ora è fuorviante.

Un'altra opzione è quella di memorizzare le versioni canoniche in unità fisse (cioè sempre chilogrammi e metri) oltre alle diverse misure originali. Le operazioni aggregate sulle unità fisse dovrebbero andare bene (tranne per il fatto che non si aggiungono temperature, per esempio), ma non si perde la misurazione originale.


1
La potenziale "interpretazione errata" che lei menziona è esattamente una delle preoccupazioni che ho sull'attuale architettura di questo database - e qualcosa che sto cercando di trovare un modo per ridurre.
kmote

1
ottimo punto sul potenziale svantaggio della soluzione nome-colonna.
kmote

1
@kmote Non è un problema semplice - abbiamo rapporti in cui le singole transazioni possono avere unità di misura originali variabili, ma c'è anche un totale - che è un totale dopo la conversione in un'unità selezionata dall'utente.
Cade Roux,

7

Una soluzione semplice che ha funzionato bene per me in passato è quella di archiviare tutti i tuoi dati nelle unità 'base'. Ad esempio, l'unità base per le lunghezze può essere millimetri e l'unità base per i pesi può essere chilogrammi. Questa soluzione potrebbe comportare la necessità di convertire alcuni dei dati esistenti nell'unità base, se non lo è già.

Una volta che hai tutti i dati nelle unità base standard, non è necessario archiviare l'unità nel database stesso, poiché ora è un presupposto a livello di sistema. Le unità visualizzate richieste per ciascun tipo di unità (ad es. Se visualizzare mm, pollici, cm, m di lunghezza) diventano un problema di dominio applicazione / client, che può essere salvato nella memoria locale.

Le tabelle di conversione delle unità per la conversione tra le varie unità supportate possono essere codificate all'interno dell'applicazione, poiché le nuove unità di misura cambiano molto raramente.

NB una soluzione correlata a un altro problema è che quando si memorizzano i timestamp in un database per memorizzarli sempre nell'unità 'base' - UTC .

Altre domande e risposte correlate sull'argomento ...


5

Poiché qualsiasi unità può essere convertita in un'altra unità dello stesso tipo Con la formula:

y = ((x + xOffset) * multiplicand / denominator) + yOffset

Vorrei creare una tabella che contenga i tipi di unità più questi 4 valori.

From Unit     To Unit      Unit Type    From Offset    Multiplicand    Denominator    To Offset
'milligrams'  'grams'      'mass'       0              1               1000           0
'grams'      'kilograms'   'mass'       0              1               1000           0
'grams'      'ounces'      'mass'       0              100000          2835           0
'ounces'     'pound'       'mass'       0              1               16             0

Dopo aver aggiunto tutte le misure che è probabile che tu converta in e da cui si trovano su entrambi i lati dell'elenco, esegui una query in cui inserisci l'operazione inversa semplicemente annullando gli offset e scambiando multiplicand e denominator e To To Unit and From Unit.

Per aggiungere la conversione tra tutti i tipi, un cross join Con alcuni filtri è possibile inserire le conversioni rimanenti.


3

Dopo aver letto la risposta di @Todd Everett, mi è venuta in mente una soluzione, quindi vado avanti e rispondo alla mia domanda. Quello che penso che ho intenzione di fare è quello di creare un separato ColumnUnitstavolo, con quattro colonne: Schema, Table, Column, UnitsID(dove è UnitsID FK ad un separato UnitsOfMeasuretabella), la mappatura in tal modo qualsiasi colonna per la sua associata unità di misura. Ovviamente il più grande svantaggio di questa idea è che gli sviluppatori dovrebbero ricordare di modificare questa tabella ogni volta che rinominano una colonna o una tabella [ forse usano un trigger DDL ? ], altrimenti il ​​sistema si romperà. Ma supponendo che tali rinominazioni siano rare e che il piccolo negozio (solo una persona, nel mio caso), questa architettura dovrebbe essere praticabile. Il vantaggio è che non è necessario apportare modifiche invasive al DB corrente e devo archiviare il valore solo una volta per ogni colonna, anziché una volta per riga, come richiederebbe la mia seconda opzione nel mio post originale.


puzzle interessante ... e idea interessante che hai. la tua idea faciliterebbe l'interrogazione, ma non sembra ottenere molto. hai appena spostato i dati di riferimento in un altro posto. ciò che mi preoccupa di più di questo design
Sir Swears-a-lot

... è che se un elemento ha più attributi è ancora necessario aggiungere più colonne. per questo motivo mi piace il suggerimento di @todd everett di un design eav.
Sir Swears-a-lot
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.