Standardlösung zur Lagerung von Maßeinheiten

7

EINLEITUNG UND RELEVANTE INFORMATIONEN:

Nehmen wir an, ich habe einen Tisch, an dem Größe und Gewicht einer Person gespeichert sind.

PersonTable < # ID int, Name varchar(50), Height double, Weight double >

Die Höhe wird in Zentimetern und das Gewicht in Kilogramm gemessen.

PROBLEM:

Mein Problem ist die Speicherung der Maßeinheit für Größe und Gewicht.

Meine Bemühungen, dies zu lösen:

  • Ich könnte versuchen, das EAV-Modell zu implementieren.
  • Ich könnte die Tabelle ändern, indem ich zusätzliche Spalten hinzufüge, die die Maßeinheit für Größe und Gewicht enthalten. So etwas wie unten:

    PersonTable < # ID int, 
                    Name varchar(50), 
                    Height double, $ HeightUnit_Id int, 
                    Weight double, $ WeightUnit_Id int >
    
    Units < #ID int, Desription varchar(20) >
    

  • HeightUnit_Id und WeightUnit_Id sind Fremdschlüssel, die auf die ID aus Tabelleneinheiten verweisen.

    FRAGE:

    Gibt es eine bessere Lösung als die offensichtlichen, die ich oben erwähnt habe, da ich beide nicht mag (EAV kann unordentlich werden, wenn es schlecht gemacht wird, und das Hinzufügen zusätzlicher "Einheitenspalten" scheint mir eine Verschwendung von Platz zu sein)?

    AlwaysLearningNewStuff
    quelle
    Sind alle Einheiten miteinander vergleichbar? Dh können alle Attribute beispielsweise in Metern gemessen werden? In diesem Fall besteht eine Idee darin, alles in derselben Einheit zu speichern (z. B. Zähler).
    Lennart
    @ Lennart: Ich weiß nicht, ob ich dich richtig verstanden habe, aber ich denke, die Antwort auf deine Frage ist ja . Jede Höhe wird in Metern gemessen.
    AlwaysLearningNewStuff
    3
    Ich würde die Feldnamen ändern, um zu verdeutlichen, für welche Maßeinheit sie verwendet werden. Höhe_cm, Gewicht_kg. Verwenden Sie dann die Anwendungsschicht, um die Benutzermessungen zu akzeptieren oder zu konvertieren. Sind Sie besorgt darüber, diese Werte im Laufe der Zeit zu verfolgen?
    Jonathan Fite
    @ JonathanFite: Sind Sie besorgt darüber, diese Werte im Laufe der Zeit zu verfolgen? Ich verstehe die Frage nicht. Lassen Sie mich versuchen zu klären: Im Moment sehe ich nicht, wie eine App, die eine Verbindung zu einer Datenbank herstellt, herausfinden würde, welche Einheiten verwendet werden. Da ich unerfahren bin und dieses Problem zum ersten Mal angehe, sehe ich zwei Lösungen: Entwickler lesen eine offizielle Dokumentation, in der die verwendeten Einheiten angegeben werden, oder ich speichere diese Informationen in der Datenbank. Ich entschied mich für die andere Lösung, da es mir logisch erschien. Vielleicht überreagiere ich ...
    AlwaysLearningNewStuff
    2
    Nun, das Gewicht und die Größe der Menschen ändern sich im Laufe der Zeit. Wenn es sich insbesondere um eine medizinische Datenbank handelt, können historische Informationen darüber, was diese Person zu bestimmten Daten gewogen hat, hilfreich sein. Für den Rest Ihrer Frage wird es immer ein Dokument geben, in dem die API erläutert wird. Wenn Sie in diesem Dokument angeben, dass "Höhe" die Größe der Person ist, ausgedrückt in cm (oder Metern oder Händen), liegt es an die Anwendungsschicht, um dies anzuzeigen und bei Bedarf in lokale / andere Einheiten zu konvertieren. Widerstehen Sie der Dokumentationsroute nicht zu stark, sie ist in der Branche üblich.
    Jonathan Fite

    Antworten:

    6

    Angenommen, die Messtypen werden nicht gemischt (dh eine bestimmte Zeile mischt nicht "kg" und "Zoll" ODER "Pfund" und "cm"), und es wird auch angenommen, dass sich zumindest ein Teil der Absicht dieser Frage jetzt darauf bezieht gelöschte verwandte Frage ( bitte beachten Sie, dass der folgende Link nur funktioniert, wenn Sie über genügend Wiederholungspunkte verfügen, um gelöschte Elemente anzuzeigen : Behandeln von zusammengesetzten Attributen mit konstantem Teil ), müssen Sie nur das von dieser Zeile verwendete Messsystem angeben . In diesem Modell hätten Sie eine einzelne MeasurementSystemTabelle mit Fremdschlüssel für alle Tabellen, die Messungen enthalten. Zum Beispiel (unter Verwendung der Microsoft SQL Server-Syntax):

    CREATE TABLE dbo.MeasurementSystem
    (
      MeasurementSystemID TINYINT NOT NULL
                          CONSTRAINT [PK_MeasurementSystem] PRIMARY KEY
                                     CLUSTERED,
      MeasurementSystemName NVARCHAR(50) NOT NULL
    );
    
    dbo.Person
    (
      PersonID            INT NOT NULL IDENTITY(1, 1)
                          CONSTRAINT [PK_Person] PRIMARY KEY
                                     CLUSTERED,
      MeasurementSystemID TINYINT NOT NULL
                          CONSTRAINT [FK_Person_MeasurementSystem]
                          FOREIGN KEY
                          REFERENCES dbo.MeasurementSystem (MeasurementSystemID),
      Name                NVARCHAR(50) NOT NULL
      Height              FLOAT,
      Weight              FLOAT,
      ...
    );
    
    INSERT INTO dbo.MeasurementSystem (MeasurementSystemID, MeasurementSystemName)
    VALUES (1, N'Metric');
    
    INSERT INTO dbo.MeasurementSystem (MeasurementSystemID, MeasurementSystemName)
    VALUES (2, N'United States customary units');
    

    Wenn Sie Messsysteme mischen und / oder mehrere Maßeinheiten zulassen, auch wenn diese auf ein System beschränkt sind (dh "mm", "cm", "m"), muss eine vorhanden sein zusätzliche Ebene, um die Zunahme der Granularität zu bewältigen, einschließlich der Notwendigkeit, ein FK-Feld pro Messspalte in der PersonTabelle zu haben. (Ich kann das obige Modell anpassen, aber ich werde auf eine Klarstellung warten, bevor ich dies tue).


    Wenn es eine relativ begrenzte Anzahl von Kombinationen verschiedener Gewichts- und Höheneinheiten gibt, können Sie stattdessen jede Zeile verwenden, um eine der akzeptierten Kombinationen darzustellen (z. B. "cm & kg", "m & kg"). "mm & kg" / "inch & lb", "foot & lb"). Und dann ist "US" vs "Metric" nur eine Eigenschaft jeder Zeile der Nachschlagetabelle. Zum Beispiel:

    CREATE TABLE dbo.MeasurementUnit
    (
      MeasurementUnitID     TINYINT NOT NULL
                                    CONSTRAINT [PK_MeasurementUnit] PRIMARY KEY
                                               CLUSTERED,
      MeasurementSystem     CHAR(1) NOT NULL, -- "M" = Metric, "U" = US 
      MeasurementSystemName NVARCHAR(50) NOT NULL, -- "Metric" or "US Nonsense"
      HeightUnitsName       NVARCHAR(20) NOT NULL, -- "Centimeters"
      HeightUnitsAlias      NVARCHAR(5) NOT NULL, -- "cm"
      WeightUnitsName       NVARCHAR(20) NOT NULL, -- "Kilograms"
      WeightUnitsAlias      NVARCHAR(5) NOT NULL -- "kg"
    );
    
    dbo.Person
    (
      PersonID            INT NOT NULL IDENTITY(1, 1)
                          CONSTRAINT [PK_Person] PRIMARY KEY
                                     CLUSTERED,
      MeasurementUnitID   TINYINT NOT NULL
                                  CONSTRAINT [FK_Person_MeasurementUnit]
                                             FOREIGN KEY
                                            REFERENCES dbo.MeasurementUnit (MeasurementUnitID),
      Name                NVARCHAR(50) NOT NULL
      Height              FLOAT,
      Weight              FLOAT,
      ...
    );
    

    Oder wenn es Kombinationen von Einheiten geben muss, die verschiedene Messsysteme kreuzen, würde ich separate Tabellen verwenden - eine für jeden Messtyp: "WeightUnits" und "HeightUnits". Ich würde keine Einheiten für Höhen und Gewichte in derselben Tabelle mischen (dh "kg" und "cm" in verschiedenen Reihen). Zum Beispiel:

    CREATE TABLE dbo.WeightUnit
    (
      WeightUnitID      TINYINT NOT NULL
                                CONSTRAINT [PK_WeightUnit] PRIMARY KEY
                                           CLUSTERED,
      MeasurementSystem CHAR(1) NOT NULL, -- "M" = Metric, "U" = US 
      WeightUnitName    NVARCHAR(50) NOT NULL, -- "Kilograms"
      WeightUnitAlias   NVARCHAR(5) NOT NULL -- "kg"
    );
    
    CREATE TABLE dbo.HeightUnit
    (
      HeightUnitID      TINYINT NOT NULL
                                CONSTRAINT [PK_HeightUnit] PRIMARY KEY
                                           CLUSTERED,
      MeasurementSystem CHAR(1) NOT NULL, -- "M" = Metric, "U" = US 
      HeightUnitName    NVARCHAR(50) NOT NULL, -- "Centimeters"
      HeightUnitAlias   NVARCHAR(5) NOT NULL -- "cm"
    );
    

    In diesem Modell hat jeder Messtyp in einer bestimmten Tabelle eine eigene persönliche FK für die Nachschlagetabelle der Maßeinheiten.

    Solomon Rutzky
    quelle
    In der Tat ist das, was Sie gerade haben, genau das, was ich brauche. Es gibt nur eine potenzielle Gefahr, die ich vermeiden muss. Die bereitgestellten Tabellen sind nur einfache Beispiele, die das Problem veranschaulichen. Im realen Modell weiß ich nicht, ob die vom Kunden verwendeten Einheiten offiziell Standard sind. Dies ist ein dummes Beispiel, aber lassen Sie uns sagen, dass sie möglicherweise eine andere Einheit für die Höhe als m / cm / mm (oder Zoll / Fuß / ...) verwenden. Ich frage mich, ob ich mich dbo.MeasurementSystemmit Säulen ändern könnte MeasuredParameterund UnitUsednur um sicher zu gehen. Beispieldaten könnten so etwas sein 1 Height cm, 2 Weight kgund so weiter ... Vielen Dank für die Antwort +1
    AlwaysLearningNewStuff
    1
    @AlwaysLearningNewStuff Wie viele Kombinationen könnte es geben? Dürfen Kunden Kennzahlentypen in Freiform eingeben? Bitte vereinfachen Sie die Beispiele nicht zu stark, da dies für uns beide irreführend und zeitaufwändig sein kann. Wenn die Kombinationen jedoch begrenzt sind, können Sie einen Eintrag pro Kombination haben: "cm & kg", "m & kg", "mm & kg" / "inch & lb", "foot & lb". Und dann ist US vs Metric nur eine Eigenschaft jeder Zeile dieser Nachschlagetabelle. Aber ich würde keine Einheiten für Höhen und Gewichte in derselben Tabelle mischen (dh "kg" und "cm" in verschiedenen Reihen). Stattdessen würde ich separate Tabellen erstellen: HeightUnits/ WeightUnits.
    Solomon Rutzky
    1
    Ich habe alles mit den Kunden besprochen und sie mögen die Idee, die Sie vorgeschlagen haben. Ich werde Ihre Antwort offiziell akzeptieren und das Kopfgeld vergeben. Danke noch einmal.
    AlwaysLearningNewStuff
    @AlwaysLearningNewStuff Danke und du bist willkommen :-). Aber welche Idee war es genau? Ich schlug eine in der Antwort und dann zwei Variationen im obigen Kommentar vor. Wenn es etwas war, das im Kommentar erwähnt wurde, würde ich es vorziehen, die Antwort mit diesen Informationen zu aktualisieren. Also lass es mich wissen.
    Solomon Rutzky
    1
    Es war der erste nach Ihrer Antwort. Sie verwenden Standardeinheiten, so dass es kein Problem geben würde. Ich würde Ihren Kommentar hinterlassen, da ich glaube, dass er für zukünftige Leser nützlich sein könnte. Nebenbei bemerkt, ich denke, ich bin damit über Bord gegangen, vielleicht sollten Einheiten irgendwo in der Dokumentation angegeben werden. Nachdem ich ein wenig recherchiert hatte, kam ich zu dem Schluss, dass dieser Ansatz der Industriestandard sein könnte ...
    AlwaysLearningNewStuff
    2

    Angesichts der Frage, wie sich diese Frage auf das Design bezieht, sind die Antworten wahrscheinlich ziemlich einfühlsam ...

    Hier ist meine Meinung dazu, wie es gestaltet werden soll. ;)

    Tabelle zum Speichern von Maßeinheiten

    CREATE TABLE measure_unit (
      measure_unit_id, -- primary key
      name -- unique key .. values such as "inch" etc
    )
    

    Ihr Personentisch ...

    CREATE TABLE person (
      person_id, -- primary key
      name,
      measurement, -- example values would be 180
      measure_unit_id -- example values would be the pkey for centimeters
    )
    

    Und dann eine Umrechnungstabelle

    CREATE TABLE measure_conversion (
      from_measure_unit_id, -- example would be pkey for centimeters
      to_measure_unit_id, -- example would be pkey for inches
      ratio -- example would be 0.393701 (centimeters * 0.393701 = inches)
      -- pkey is composite between both from and to values
    )
    

    Wenn eine Maßeinheit keinen Eintrag in der Kennzahlenumrechnungstabelle für einen bestimmten anderen Einheitentyp hat, ist keine direkte Umrechnung verfügbar. (Zum Beispiel würde cm -> Zoll funktionieren, cm -> Stunden jedoch nicht.) Die Anzeige Ihrer Messungen in verschiedenen Einheiten sollte einfach sein.

    Ihre Maßeinheit kann alles sein, was Sie wollen (Entfernung / Zeit / usw.) ... aber Sie möchten möglicherweise einen Maßtyp hinzufügen. Sie sind sich nicht sicher, ob ich mir darüber Sorgen machen würde - hängt vom Anwendungsfall ab.

    Joishi Bodio
    quelle
    Es wird keine Umrechnung geben, jede Höhe wird in Metern gemessen, und ich kann garantieren, dass in Zukunft keine Umrechnung mehr erforderlich ist. Ich denke, das lässt mich nur mit measure_unitTisch, richtig?
    AlwaysLearningNewStuff
    Wenn Sie immer nur eine Maßeinheit verwenden, würde das in OP vorgeschlagene Design funktionieren ... aber ich würde dieses Design trotzdem empfehlen (und ja, Sie hätten nicht mehr die Tabelle Measure_Conversion)
    Joishi Bodio,
    2

    Wenn Ihre Größen- / Gewichtsmaßeinheiten tatsächlich fest sind , dh Größe = CMs, Gewicht = KGs, würde ich keine zusätzlichen Spalten (oder Logik) einführen, um die Maßeinheit anzugeben. Stattdessen würde ich einfach den Spaltennamen ändern, z

    create table Person (ID int, Name varchar(50), Height_CM double, Weight_KG double)

    Auf diese Weise kann ich alle Verwirrungen über die Maßeinheit für Spalten Höhe und Gewicht beseitigen.

    jyao
    quelle
    0

    Dies hängt davon ab, was Sie entwerfen. Ein normalisiertes OLTP-System verfügt über eine separate Measures-Tabelle (oder einen solchen Namen), die für jede mögliche Maßeinheit referenzielle Integritäts- und Leistungsoptimierungen bietet.

    Wenn Sie Analysen durchführen und selten mit Einheiten arbeiten und weniger Konvertierungen durchführen, kann dies als Attribut gespeichert werden. Dies wäre immer noch selten - so etwas wie Umfrageantworten oder ein Industriestandard wie Quadratmeter für Immobilien. Aber was wird sonst noch gemessen und macht bei Immobilien Sinn? Grundrisse? Jetzt haben wir Zoll ... und Quadrate und Kubik. Wir sind zurück zu einem normalisierten Design.

    Für die Höhe sind verschiedene Maßnahmen anwendbar, die in verschiedenen Zusammenhängen durchaus sinnvoll sind. Wahrscheinlich eine gute Idee, ein Design wie dieses zu verwenden:

    dbo.PersonHeight
    Height     MeasureFK
    62           2
    
    dbo.UnitsOfMeasure
    MeasureID  MeasureDescription
    2          Inches
    3          Centimeters
    

    Mit einem solchen Design können Sie jetzt ganz einfach eine Nachschlagetabelle erstellen:

    dbo.UnitConversions
    FromMeasureID    ToMeasureID    Conversion
    2                 3             0.39370079
    
    Dave
    quelle
    Es wird keine Umrechnung geben, jede Höhe wird in Metern gemessen, und ich kann garantieren, dass in Zukunft keine Umrechnung mehr erforderlich ist.
    AlwaysLearningNewStuff