支持的版本: 当前 (17) / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3

F.37. seg — 用于线段或浮点数间隔的数据类型 #

此模块实现了一个数据类型 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...21 .. 21..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] 为 true。

seg >> segboolean

第一个 seg 是否完全位于第二个 seg 的右侧?如果 a > d,则 [a, b] >> [c, d] 为 true。

seg &< segboolean

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

seg &> segboolean

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

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

(+-) 转换为常规范围的机制在确定边界有效数字位数方面并不完全准确。例如,如果生成的区间包含 10 的幂,它会在下边界添加额外的数字。

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. ,阿贡国家实验室数学与计算机科学部。

我首先要感谢 Joe Hellerstein 教授(https://dsf.berkeley.edu/jmh/)阐明了 GiST 的要点(http://gist.cs.berkeley.edu/)。我也感谢所有过去和现在的 Postgres 开发人员,他们使我能够创造自己的世界并在其中不受干扰地生活。 我还要感谢阿贡实验室和美国能源部多年来对我数据库研究的忠实支持。

提交更正

如果您在文档中发现任何不正确的内容,与您特定功能的体验不符或需要进一步澄清的内容,请使用此表单报告文档问题。