Bester Weg, um Einheiten in der Datenbank zu speichern

21

Ich habe eine große (SQLServer) Datenbank mit Hunderten von Spalten geerbt, die Beträge der einen oder anderen Sache darstellen. Die Einheiten für diese Werte (z. B. "Gallonen", "Zoll" usw.) werden im Feld "MS_Description" der erweiterten Eigenschaften gespeichert. Ich frage mich, ob es einen besseren Weg gibt, diese Informationen zu speichern. Ich nehme an, es ist zu Dokumentationszwecken in Ordnung, aber es wäre schwierig, robuste Berechnungen zur Einheitenumrechnung basierend auf diesen Daten durchzuführen. Zu diesem Zeitpunkt bin ich noch nicht bereit, eine invasive Änderung vorzunehmen. Wenn ich jedoch die Möglichkeit dazu bekomme, was ist diesbezüglich die empfohlene Best Practice? Zu den Optionen, die mir aus dem Kopf gehen, könnten gehören:

  • Ändern Sie den Spaltennamen in eingeschlossene Einheiten (z. B. "TotalVolumeInGallons". Dies würde die Informationen ein wenig leichter verfügbar machen, aber es scheint mir immer noch schwach.)
  • Fügen Sie eine separate "Einheiten" -Spalte hinzu, um jeder "Betrag" -Spalte zu entsprechen (diese Spalte könnte nvarchar sein ODER ein Fremdschlüssel für eine separate Einheitentabelle, wodurch die Berechnung von Einheitenumrechnungen vereinfacht wird Viele Spalten könnten die Größe meiner Datenbank ziemlich verdoppeln - mit furchtbar redundanten Daten.)
  • Erstellen Sie ein neues Feld in den erweiterten Eigenschaften, das speziell für Einheiten bestimmt ist. (Leider glaube ich nicht, dass dies ein Fremdschlüssel für eine Einheitentabelle sein kann.)
  • Gibt es eine andere Idee, die ich übersehen habe?

UPDATE: Nachdem ich @Todd Everetts Antwort gelesen hatte, kam mir eine mögliche Lösung in den Sinn, sodass ich meine eigene Frage beantworten werde. (Siehe unten)

kmote
quelle
Es wird empfohlen, ein einziges Messsystem für die gesamte Anwendung universell und konsistent einzusetzen. SI wäre das System der Wahl. Werte in anderen Systemen werden beim Laden oder in der Präsentationsebene konvertiert, wobei jeder Benutzer seinen bevorzugten Satz auswählen kann.
Michael Green

Antworten:

12

Da Sie Hunderte von Spalten erwähnen, würde ich ein EAV-Design in Betracht ziehen . Während Joe Celko davor warnt , denke ich, dass es in Ihrem Anwendungsfall anwendbar sein könnte. Es hört sich so an, als wären alle Ihre "Beträge" Zahlen, sodass Sie die von Joe beschriebenen Casting-Probleme und die Notwendigkeit vermeiden würden, jeden "Wert" zu einer Zeichenfolge zu machen. Es funktioniert sogar noch besser, wenn alle Beträge ganze Zahlen sind, kann aber auch funktionieren, wenn einige dezimal sind. In Anbetracht der Maßeinheiten können Sie einen Schritt weiter gehen und ein Modell im Stil eines "universellen Datenmodells" implementieren, das auf diesem Artikel von David Hay basiert und in seinem Buch " Datenmodellmuster: Konventionen des Denkens" beschrieben ist. Dieses Modell hat den zusätzlichen Vorteil, dass Sie konfigurieren können, welche "Beträge" für welche "Dinge" gelten, wenn Sie dies benötigen. Ein weiterer Schritt, der in dem Buch auf Seite 181 gezeigt wird, ist eine Maßeinheitenkonvertierungstabelle, mit der Sie zwischen den verschiedenen Maßeinheiten konvertieren können. Hier ist ein Beispiel:

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

Dies besagt, dass der erste Schritt, um von Kg zu Lb zu konvertieren, darin besteht, Kg mit 2,2 zu multiplizieren. Es gibt auch eine Konstante, wenn eine Konvertierung auch einen konstanten Wert enthalten muss, und die Möglichkeit, mehrere Schritte zu erstellen. Wenn Sie also beispielsweise Celsius in Fahrenheit umrechnen, multiplizieren Sie Celsius mit 1,8 und addieren dann 32. Der Schlüssel wäre der von UOM, der zu UOM und der Berechnungsschritt.

Das sind meine 2 Cent wert. Ich hoffe, diese Referenzen geben Ihnen Anlass zu guten Überlegungen, falls Sie jemals die Gelegenheit haben sollten, einen Neustart des aktuellen Designs durchzuführen.

Todd Everett
quelle
Vielen Dank für einige sehr interessante Denkanstöße - ich habe viel gelernt. Ich glaube jedoch nicht, dass EAV in meinem Fall das geeignete Modell ist (wenn ich Ihren Vorschlag richtig verstehe), da wir zwar Hunderte von Spalten haben, diese aber keineswegs spärlich sind. Dies hat jedoch eine verwandte Idee ausgelöst (siehe UPDATE in meinem ursprünglichen Beitrag).
kmote
Ihre Idee klingt ziemlich gut für mich - ich kann mir keine anderen Probleme dabei ausdenken, als die, auf die Sie bereits hingewiesen haben. Wenn Spalten jedoch umbenannt / geändert werden können, ist dies in jedem Design ein Problem. Hier macht Zusammenarbeit Spaß - eine Idee, an die keiner von uns gedacht hat!
Todd Everett
8

Alle Arbeit.

Beachten Sie, dass Sie im zweiten Fall keine Äpfel und Apfelsinen hinzufügen können und die Daten daher außergewöhnlich leicht falsch interpretiert werden können.

Beachten Sie auch, dass Konvertierungen nicht sehr sicher sind und Rundungsfehler, Überläufe usw. verursachen können.

Darüber hinaus gibt es physikalische Probleme wie das spezifische Gewicht und die Temperatur. Um 20 Gallonen Wasser in Pfund umzuwandeln, müssten Sie die Dichte des Wassers kennen. Da sich die Dichte des Wassers jedoch mit der Temperatur ändert, müssen Sie möglicherweise entweder die Dichte gleichzeitig mit der Messung oder die Temperatur in ähnlicher Weise kennen und einen Volumenkorrekturfaktor verwenden.

Bei den erweiterten Eigenschaften ist dies nur für die Dokumentation hilfreich - ein guter Spaltenname ist besser für die Dokumentation. Das Problem mit der Spalte, die namentlich in einer festen Einheit enthalten ist, besteht darin, dass Sie sich in eine Ecke stürzen, wenn Sie die Maßeinheiten ändern eine eigene Datenbank, aber der Spaltenname ist jetzt irreführend.

Eine andere Möglichkeit besteht darin, kanonische Versionen zusätzlich zu den variierenden Originalmaßen in festen Einheiten (dh immer Kilogramm und Meter) zu speichern. Aggregierte Operationen an den festen Einheiten sollten in Ordnung sein (außer Sie würden zum Beispiel keine Temperaturen hinzufügen), aber Sie verlieren nicht die ursprüngliche Messung.

Cade Roux
quelle
1
Die mögliche "Fehlinterpretation", die Sie erwähnen, ist genau eines der Anliegen, die ich in Bezug auf die aktuelle Architektur dieser Datenbank habe - und etwas, das ich versuchen möchte, einen Weg zu finden, dies zu reduzieren.
kmote
1
Großer Punkt über den möglichen Nachteil der Lösung mit Spaltennamen.
kmote
1
@kmote Es ist kein einfaches Problem - wir haben Berichte, in denen die einzelnen Transaktionen unterschiedliche ursprüngliche Maßeinheiten aufweisen können, aber es gibt auch eine Gesamtsumme - die sich nach der Umrechnung in eine vom Benutzer ausgewählte Einheit ergibt.
Cade Roux
7

Eine einfache Lösung, die in der Vergangenheit für mich gut funktioniert hat, besteht darin, alle Ihre Daten in den Basiseinheiten zu speichern. Beispielsweise kann Ihre Basiseinheit für Längen Millimeter und Ihre Basiseinheit für Gewichte Kilogramm sein. Diese Lösung kann dazu führen, dass einige Ihrer vorhandenen Daten in die Basiseinheit konvertiert werden müssen, sofern dies noch nicht geschehen ist.

Sobald Sie alle Daten in den Standard-Basiseinheiten haben, müssen Sie die Einheit nicht mehr in der Datenbank selbst speichern, da dies jetzt eine systemweite Annahme ist. Die angezeigten Einheiten, die für jeden Einheitentyp erforderlich sind (z. B. ob mm, Zoll, cm, m für die Länge angezeigt werden sollen), werden zu einem Anwendungs- / Clientdomänenproblem, das lokal gespeichert werden kann.

Die Einheitenumrechnungstabellen für die Umrechnung zwischen den verschiedenen unterstützten Einheiten können in Ihrer Anwendung fest codiert werden, da sich neue Maßeinheiten äußerst selten ändern.

Eine verwandte Lösung für ein anderes Problem ist, dass beim Speichern von Zeitstempeln in einer Datenbank diese immer in der Basiseinheit (UTC) gespeichert werden .

Weitere verwandte Fragen und Antworten zum Thema ...

dodgy_coder
quelle
5

Da jede Einheit in eine andere Einheit desselben Typs umgewandelt werden kann, gilt folgende Formel:

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

Ich würde eine Tabelle erstellen, die die Einheitentypen plus diese 4 Werte enthält.

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

Nachdem Sie auf beiden Seiten der Liste alle Maße hinzugefügt haben, zu denen Sie wahrscheinlich konvertieren werden, führen Sie eine Abfrage aus, in der Sie die inverse Operation einfügen, indem Sie einfach die Offsets negieren und den Multiplikanden und den Nenner sowie die Einheiten To und From vertauschen.

Um die Konvertierung zwischen allen Typen hinzuzufügen, kann ein Cross-Join mit einigen Filtern die verbleibenden Konvertierungen einfügen.

peroyhav
quelle
3

Nachdem ich die Antwort von @Todd Everett gelesen hatte, fiel mir eine Lösung ein, und ich werde meine eigene Frage beantworten. Was ich denke , ich werde eine separate zu tun ist , erstellen ColumnUnitsTabelle mit vier Spalten: Schema, Table, Column, UnitsID(wo UnitsID ist FK in eine separate UnitsOfMeasureTabelle), so dass die Abbildung jeder gegebenen Spalte mit ihrer zugehörigen Maßeinheit. Offensichtlich ist der größte Nachteil dieser Idee, dass Entwickler daran denken müssen, diese Tabelle zu bearbeiten, wenn sie eine Spalte oder Tabelle umbenennen [ vielleicht einen DDL-Trigger verwenden ? ], sonst bricht das System zusammen. Unter der Annahme, dass solche Umbenennungen selten sind und der Dev-Shop klein ist (in meinem Fall nur eine Person), sollte diese Architektur funktionsfähig sein. Der Vorteil ist, dass keine invasiven Änderungen an der aktuellen Datenbank vorgenommen werden müssen und ich den Wert nur einmal für jede Spalte speichern muss, anstatt einmal pro Zeile, wie es meine zweite Option in meinem ursprünglichen Beitrag erfordern würde.

kmote
quelle
interessantes Puzzle ... und interessante Idee, die Sie haben. Ihre Idee würde die Abfrage erleichtern, scheint aber nicht viel zu bewirken. Sie haben gerade die Referenzdaten an einen anderen Ort verschoben. Was mich an diesem Design am meisten stört
Sir Swears-a-lot
... bedeutet, dass Sie weitere Spalten hinzufügen müssen, wenn ein Element mehr Attribute hat. aus diesem grund gefällt mir @todd everetts vorschlag eines eav-designs.
Sir Swears-a-lot