kmo*_*ote 23 database-design sql-server metadata
我继承了一个包含数百个列的大型 (SQLServer) 数据库,这些列代表一件事或另一件事的数量。这些值的单位(例如“加仑”、“英寸”等)存储在扩展属性的 MS_Description 字段中。我想知道是否有更好的方法来存储这些信息。我认为用于文档目的很好,但很难根据这些数据进行可靠的单位换算计算。在这一点上,我不准备进行侵入性更改,但如果我有机会这样做,在这方面推荐的最佳实践是什么?在我的脑海中,选项可能包括:
更新:阅读@Todd Everett 的回答后,我想到了一个可能的解决方案,所以我将继续回答我自己的问题。(见下文)
Tod*_*ett 13
既然你提到了数百列,我会考虑EAV 设计。虽然 Joe Celko对此提出警告,但我认为它可能适用于您的用例。听起来您的所有“金额”都是数字,因此您将避免 Joe 描述的转换问题以及将每个“值”设为字符串的需要。如果所有金额都是整数,效果会更好,但如果有些金额是小数,也可以。鉴于度量单位,您可以更进一步,根据David Hay 的这篇文章并在他的著作Data Model Patterns: Conventions of Thought 中概述,实现一个“通用数据模型”风格的模型. 如果您需要,此模型具有配置哪些“金额”适用于哪些“事物”的额外优势。书中第 162 页上显示的一个附加步骤是一个度量单位转换表,您可以使用它在不同的度量单位之间进行转换。下面是一个例子:
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
Run Code Online (Sandbox Code Playgroud)
这表示要将 Kg 转换为 Lb,第一步是将 Kg 乘以 2.2。如果转换还必须包含常量值以及创建多个步骤的能力,则还有一个常量。因此,当将摄氏温度转换为华氏温度时,您将摄氏度乘以 1.8,然后再加上 32。关键是从 UOM、到 UOM 和计算步骤。
那是我的 2 美分。如果您有机会重新启动当前的设计,我希望这些参考资料能给您一些很好的思考。
所有的工作。
请注意,在第二种情况下,您不能添加苹果和橙子,因此数据非常容易被误解。
另请注意,转换不是很安全,并且容易出现舍入错误、溢出等。
此外,还有比重和温度等物理问题。将 20 加仑水转换为磅需要您知道水的密度。但是水的密度随温度而变化,因此您可能需要知道与测量同时发生的密度或类似的温度,并使用体积校正因子。
在扩展属性的情况下,这仅适用于文档 - 一个好的列名更适合文档。隐含在名称中的固定单位的问题是,当您更改度量单位时,您最终会将自己置于角落 - 新客户想要以桶而不是加仑为单位的石油 - 这会很好,因为他们的数据在它自己的数据库,但列名现在具有误导性。
除了不同的原始测量值之外,另一种选择是以固定单位(即始终为千克和米)存储规范版本。固定单位上的聚合操作应该没问题(例如,除非您不会添加温度),但您不会丢失原始测量值。
小智 7
过去对我来说效果很好的一个简单解决方案是将所有数据存储在“基本”单位中。例如,长度的基本单位可能是毫米,而重量的基本单位可能是公斤。此解决方案可能需要将一些现有数据转换为基本单位(如果尚未转换)。
一旦您拥有标准基本单位中的所有数据,就无需将单位存储在数据库本身中,因为它现在是一个系统范围的假设。每种单位类型所需的显示单位(例如,长度是否显示mm、inches、cm、m)成为应用程序/客户端域问题,可以保存到本地存储。
用于在各种支持单位之间进行转换的单位转换表可以在您的应用程序中进行硬编码,因为新的度量单位很少发生变化。
注意另一个问题的相关解决方案是,在数据库中存储时间戳时,始终将它们存储在“基本”单位 - UTC 中。
关于该主题的另一个相关问答...
这包含一些很好的信息,说明为什么使用浮点列类型是存储真实世界测量值的最佳方法。
小智 5
由于任何单位都可以转换为相同类型的另一个单位 用公式:
y = ((x + xOffset) * multiplicand / denominator) + yOffset
Run Code Online (Sandbox Code Playgroud)
我会创建一个包含单位类型加上这 4 个值的表。
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
Run Code Online (Sandbox Code Playgroud)
在添加了您可能在列表的任一侧进行转换和转换的所有测量值后,运行查询,通过简单地否定偏移并交换被乘数和分母以及 To Unit 和 From Unit 来插入逆运算。
要在所有类型之间添加转换,交叉连接一些过滤器可以插入剩余的转换。
阅读@Todd Everett 的回答后,我想到了一个解决方案,所以我将继续回答我自己的问题。我认为我要做的是创建一个单独的ColumnUnits表,其中包含四列:Schema, Table, Column, UnitsID(其中 UnitsID 是 FK 到单独的UnitsOfMeasure表),从而将任何给定列映射到其关联的度量单位。显然,这个想法的最大缺点是开发人员在重命名列或表时必须记住编辑此表[也许使用DDL 触发器?],否则系统会崩溃。但假设这种重命名很少见,并且开发车间很小(在我的例子中只有一个人),那么这种架构应该是可行的。优点是不必对当前数据库进行侵入性更改,并且我只需为每列存储一次值,而不是像我原始帖子中的第二个选项所要求的那样每行存储一次。
| 归档时间: |
|
| 查看次数: |
20926 次 |
| 最近记录: |