Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

F.37. seg — 直线段或浮点数区间数据类型 #

F.37.1. 缘由
F.37.2. 语法
F.37.3. 精度
F.37.4. 用法
F.37.5. 注释
F.37.6. 鸣谢

此模块实现了表示直线段或浮点数区间的 seg 数据类型。 seg 可以表示区间端点的模糊性,使其特别适用于表示实验室测量值。

此模块被认为是“可信”,也就是说,它可以由具有在当前数据库上拥有 CREATE 权限的非超级用户安装。

F.37.1. 缘由 #

测量中的几何通常比数值连续统一体中的点更复杂。测量通常是该连续统一体中具有某种模糊限制的线段。测量结果以区间的形式出现,这既是因为模糊性和随机性,也因为待测量值在本质上可能是区间,表示某种条件,例如蛋白质稳定性的温度范围。

使用常识可知,以区间而非数字对的形式存储此类数据更加方便。在实践中,它甚至在大多数应用程序中都更有效。

在常识的指导下,模糊限制表明使用传统的数字数据类型会导致一定程度的信息丢失。考虑这一点:仪器读数为 6.50,您会将此读数输入到数据库。获取此读数时会发生什么?观察

test=> select 6.50 :: float8 as "pH";
 pH
---
6.5
(1 row)

在测量领域,6.50 与 6.5 并不同。有时,差异可能是至关重要的。实验人员通常会写下(并发布)他们信任的数字。6.50 实际上是包含在更大且更模糊的区间 6.5 中的模糊区间,其中心点(可能)是它们唯一共有的特征。我们绝对不想让这样不同的数据项看起来相同。

结论?最好有一种特殊的数据类型,可以以任意可变精度记录区间的限制。可变是指每个数据元素都记录自己的精度。

查看此内容

test=> select '6.25 .. 6.50'::seg as "pH";
          pH
------------
6.25 .. 6.50
(1 row)

F.37.2. 语法 #

使用一个或两个浮点数,通过范围运算符(.....)连接而成,可以形成区间的外部表示形式。或者,可以将其指定为中心点加上或减去偏差。还可以存储可选确定性指示符(<>~)。不过(所有内置运算符都会忽略确定性指示符。)表 F.27 提供了允许表示形式的概述;表 F.28 显示了一些示例。

表 F.27中,xydelta 表示浮点数。xy 可以有确定性指示符,但 delta 不可以。

表 F.27. seg 外部表示形式

x 单个值(零长度区间)
x .. y xy 的区间
x (+-) delta 间隔从 x - deltax + delta
x .. 下限为 x 的开区间
.. x 上限为 x 的开区间

表 F.28. 有效的 seg 输入的示例

5.0 创建零长度区间段(如果您愿意的话,就是点)
~5.0 创建零长度区间段并在数据中记录 ~~ 会被 seg 操作忽略,但会被保留为注释。
<5.0 在 5.0 处创建一个点。 < 会被忽略,但会被保留为注释。
>5.0 在 5.0 处创建一个点。 > 会被忽略,但会被保留为注释。
5(+-)0.3 创建区间 4.7 .. 5.3。 请注意 (+-) 符号并未保留。
50 .. 大于或等于 50 的所有内容
.. 0 小于或等于 0 的所有内容
1.5e-2 .. 2E-2 创建一个区间 0.015 .. 0.02
1 ... 2 1...2 相同,或 1 .. 2,或 1..2(范围运算符周围的空格会被忽略)

由于 ... 运算符在数据源中被广泛使用,因此允许作为 .. 运算符的一个变体拼法。不幸的是,这产生了解析歧义:无法明确 0...23 中的上限到底是 23 还是 0.23。可以通过在 seg 输入中所有数字的小数点前面至少要求一个数字来解决这个问题。

为了进行健全检查,seg 拒绝下限大于上限的区间,例如 5 .. 2

F.37.3. 精度 #

seg 值在内部存储为 32 位浮点数的成对数字。这意味着小数位多于 7 位的数字会被截断。

小数位少于或等于 7 位的数字将保留其原始精度。也就是说,如果您的查询返回 0.00,您将可以确定尾随零不是格式调整的人工制品:它们反映原始数据的精度。前导零的位数不影响精度:数字 0.0067 被认为只有 2 个小数位。

F.37.4. 用法 #

seg 模块包括一个 seg 值的 GiST 索引操作符类。 GiST 操作符类支持的操作符显示在 表 F.29 中。

表 F.29. Seg GiST 操作符

操作符

描述

seg << segboolean

第一个 seg 是否完全在第二个 seg 的左边?当 b < c 时,[a, b] << [c, d] 为真。

seg >> segboolean

第一个 seg 是否完全在第二个 seg 的右侧?如果 a > d,则 TRUE [a, b] >> [c, d]

seg &< segboolean

第一个 seg 是否不扩展到第二个 seg 的右侧?如果 b <= d,则 TRUE [a, b] &< [c, d]

seg &> segboolean

第一个 seg 是否不扩展到第二个 seg 的左侧?如果 a >= c,则 TRUE [a, b] &> [c, d]

seg = segboolean

两个 seg 是否相等?

seg && segboolean

两个 seg 是否重叠?

seg @> segboolean

第一个 seg 是否包含第二个 seg

seg <@ segboolean

第一个 seg 是否包含在第二个 seg 中?


除了上述运算符之外,表 9.1 中所示的常用比较运算符也可用于 seg 类型。这些运算符首先比较 (a) 到 (c),如果它们相等,则比较 (b) 到 (d)。在大多数情况下,这会导致相当不错的排序,在使用这种类型时,如果您想使用 ORDER BY,这会很有用。

F.37.5. 注释 #

有关使用示例,请参见回归测试 sql/seg.sql

(+-) 转换为常规范围的机制在确定边界的有效数字位数时并不完全准确。例如,如果结果区间包含十的幂,它将为较低边界添加一个额外的数字

postgres=> select '10(+-)1'::seg as seg;
      seg
---------
9.0 .. 11             -- should be: 9 .. 11

R 树索引的性能在很大程度上取决于输入值的初始顺序。在 seg 列上对输入表进行排序可能非常有帮助;有关示例,请参见脚本 sort-segments.pl

F.37.6. 致谢 #

原始作者:Gene Selkov, Jr. , 数学与计算机科学分部,Argonne 国家实验室。

首先我要感谢 Prof. Joe Hellerstein (https://dsf.berkeley.edu/jmh/),他阐明了 GiST (http://gist.cs.berkeley.edu/) 的要旨。我还要感谢所有过去的和现在的 Postgres 开发者,因为他们让我能够创造我自己的世界,并安然无恙地生活其中。我还要感谢 Argonne 实验室和美国能源部,因为他们多年来一直忠实地支持我的数据库研究。