我正在使用原生作为有理数提供的数据。我在C#中有一个光滑的generic C# class which beautifully represents this data,允许转换为许多其他形式。不幸的是,当我转身并希望将其存储在SQL中时,我想到了几个解决方案,但没有一个非常令人满意。
这是一个例子。我有原始值2/3
,我的new Rational<int>(2, 3)
可以在C#中轻松处理。我想到的将其存储在数据库中的选项如下:
就像十进制/浮点一样,即各种精度和精确度的值= 0.66666667
。
优点:这允许我查询数据,例如找到值&lt; 1。
缺点:它失去了准确性,当我在UI中显示这个简单的值时它很难看。
存储为两个完全整数字段,例如numerator = 2
,分母= 3
各种精确度和精确度。
优点:这使我能够精确地表示原始值,并在以后以最简单的形式显示它。
缺点:我现在有两个字段来表示这个值,现在查询很复杂/效率低,因为每个查询都必须执行算术,例如find numerator / denominator&lt; 1。
序列化为字符串数据,即"2/3"
。我将能够知道最大字符串长度并且有一个varchar可以容纳这个。
优点:我回到了一个领域,但有一个确切的代表。
缺点:查询几乎被破坏并支付序列化费用。
#1&amp;的组合#2。 优点:轻松/高效地查询值范围,和在UI中具有精确值。 缺点: 三个字段(!?!)来保存一个数据,必须保持多个同步表示,这会破坏D.R.Y。
#1&amp;的组合#3。 优点:轻松/高效地查询值范围,和在UI中具有精确值。 缺点:返回两个字段以保存一个数据,必须保持多个表示同步,这会破坏D.R.Y.,并且必须支付额外的序列化费用。
有没有人有另一种开箱即用的解决方案比这些更好?还有其他我不考虑的事情吗?有没有一种相对简单的方法在SQL中做到这一点,我只是不知道?
答案 0 :(得分:7)
如果您使用的是SQL Server 2005或2008,则可以选择define your own CLR data types:
从SQL Server 2005开始,你 可以使用用户定义的类型(UDT) 扩展标量类型系统 服务器,启用CLR存储 SQL Server数据库中的对象。的UDT 可以包含多个元素 有行为,区分他们 来自传统的别名数据类型 它由一个SQL Server组成 系统数据类型。
因为UDT是由访问的 系统作为一个整体,它们的用途 复杂的数据类型可能是负面的 影响表现。复杂的数据是 通常使用最好的模型 传统的行和表。 UDT in SQL Server非常适合 以下内容:
- 日期,时间,货币和扩展数字类型
- 地理空间应用
- 编码或加密数据
如果你能忍受这些限制,我无法想象一种更好的方法来映射你已经在自定义类中捕获的数据。
答案 1 :(得分:6)
我可能会使用选项#4,但是使用第3列的计算列来避免同步/干扰问题(也意味着您实际上只存储了2列,避免了“三个字段”问题)。
在SQL server中,计算列的定义如下:
CREATE TABLE dbo.Whatever(
Numerator INT NOT NULL,
Denominator INT NOT NULL,
Value AS (Numerator / Denominator) PERSISTED
)
(注意你可能需要做一些类型转换和验证Denominator不为零等)。
此外,SQL 2005添加了一个PERSISTED计算列,可以在查询时删除计算。
答案 2 :(得分:2)
语言C#或其他语言将在精度的给定位置舍入2 / 3rds。如果您正在使用的任何内容都可以使用10的科学记数法的十进制值,那么在db中相应地设置精度。
如果确实需要精确度,那么将分子和分子分开。分母。这将确保您始终可以访问所需的任何精度,并且可以使用computed column来表示快速过滤的值:
numerator INT,
denominator INT,
result AS CASE WHEN denominator > 0 THEN numerator / denominator ELSE NULL END
答案 3 :(得分:0)
我已经尝试使用SQL Server 2008中的geometry data type来存储和操作有理数。基本上,我假设分子进入X槽,分母进入虚构几何点的Y槽。
这对我的需求有好处,但对你来说可能毫无用处。这取决于您的优先级(性能,代码可读性等)。我个人发现用于几何数据操作的T-SQL很难编写和读取。
答案 4 :(得分:0)
修改:添加更多链接和引号
“当Mathematica对有理数进行操作时,无论需要多少位数,它都会给出一个精确的结果”来自here
Another good read,但你必须实现它我想