支持的版本: 当前 (17) / 16 / 15 / 14 / 13
开发版本: 开发版
不支持的版本: 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 是否完全在第二个的左侧?如果 b < c,则 [a, b] << [c, d] 为真。

seg >> segboolean

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

seg &< segboolean

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

seg &> segboolean

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

seg = segboolean

两个 seg 是否相等?

seg && segboolean

两个 seg 是否重叠?

seg @> segboolean

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

seg <@ segboolean

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

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

提交更正

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