存储度量单位的标准解决方案

Alw*_*uff 7 database-design

介绍和相关信息:

假设我有一张表,用于存储一个人的身高和体重,如下所示:

PersonTable < # ID int, Name varchar(50), Height double, Weight double >
Run Code Online (Sandbox Code Playgroud)

身高以厘米为单位,体重以公斤为单位。

问题:

我的问题是关于存储身高和体重的计量单位。

我为解决这个问题所做的努力:

  • 我可以尝试实现EAV模型。
  • 我可以通过添加额外的列来修改表格,这些列包含 Height 和 Weight 的度量单位?像下面这样:

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

  • HeightUnit_Id 和 WeightUnit_Id 是引用表 Units 中的 Id 的外键。

    题:

    有没有比我上面提到的明显解决方案更好的解决方案,因为我不喜欢两者(如果做得不好,EAV 会变得混乱,并且添加额外的“单位列”对我来说似乎是浪费空间)?

    Sol*_*zky 6

    假设测量类型不会混合(即任何特定行不会混合“公斤”和“英寸”或“磅”和“厘米”),并且还假设该问题的至少部分意图现在与此相关删除相关问题(请注意,除非您有足够的代表点来查看已删除的项目,否则以下链接将不起作用: 处理具有常量部分的复合属性),那么您只需要指出该行使用的度量系统。在此模型中,您将有一个MeasurementSystem表,该表是外键到任何包含测量值的表。例如(使用 Microsoft SQL Server 语法):

    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');
    
    Run Code Online (Sandbox Code Playgroud)

    如果您将混合测量系统和/或如果您将允许多个测量单位,即使仅限于一个系统(即允许“毫米”、“厘米”、“米”),则需要有一个额外的层来处理粒度的增加,包括需要Person表中的每个度量列都有一个 FK 字段。(我可以调整上面的模型以适应这一点,但在这样做之前会等待一些澄清)。


    或者,如果各种重量单位和高度单位的组合数量相当有限/有限,那么您可以改为使用每一行来表示可接受的组合之一(例如“cm & kg”、“m & kg”、 “毫米和公斤”/“英寸和磅”,“英尺和磅”)。然后“US”与“Metric”只是查找表每一行的属性。例如:

    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,
      ...
    );
    
    Run Code Online (Sandbox Code Playgroud)

    或者,如果需要跨不同测量系统的单位组合,那么我将使用单独的表格 - 每个测量类型一个:“WeightUnits”和“HeightUnits”。我不会在同一个表中混合使用高度和重量单位(即不同行上的“kg”和“cm”)。例如:

    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"
    );
    
    Run Code Online (Sandbox Code Playgroud)

    在此模型中,任何给定表中的每种测量类型都有其自己的测量单位查找表的个人 FK。