2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 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.39. seg — 線段或浮點區間資料型別 #

此模組實現了一個名為 seg 的資料型別,用於表示線段或浮點區間。seg 可以表示區間端點的不確定性,因此特別適用於表示實驗室測量結果。

此模組被認為是受信任的,這意味著非超級使用者也可以在其擁有的資料庫上安裝它,前提是他們具有 CREATE 許可權。

F.39.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.39.2. 語法 #

區間的外部表示形式使用一個或兩個浮點數,並用範圍運算子(.....)連線。或者,也可以指定為中心點加上或減去一個偏差。還可以儲存可選的確定性指示符(<>~)。(儘管如此,所有內建運算子都會忽略確定性指示符。) 表 F.29 提供了允許的表示形式的概述; 表 F.30 顯示了一些示例。

表 F.29 中,xydelta 表示浮點數。xy 可以加上確定性指示符,但 delta 不可以。

表 F.29. seg 外部表示

x 單值(零長度區間)
x .. y 區間從 xy
x (+-) delta 區間從 x - deltax + delta
x .. 下界為 x 的開區間
.. x 上界為 x 的開區間

表 F.30. 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.39.3. 精度 #

seg 值在內部儲存為一對 32 位浮點數。這意味著超過 7 位有效數字的數字將被截斷。

具有 7 位或更少有效數字的數字會保留其原始精度。也就是說,如果您的查詢返回 0.00,您將確信末尾的零不是格式化產生的偽影:它們反映了原始資料的精度。前導零的數量不影響精度:0.0067 這個值被認為只有 2 位有效數字。

F.39.4. 用法 #

名為 seg 的模組包含一個用於 seg 值的 GiST 索引運算子類。GiST 運算子類支援的運算子顯示在 表 F.31 中。

表 F.31. Seg GiST 運算子

運算子

描述

seg << segboolean

第一個 seg 是否完全在第二個 seg 的左邊?[a, b] << [c, d] 當 b < c 時為真。

seg >> segboolean

第一個 seg 是否完全在第二個 seg 的右邊?[a, b] >> [c, d] 當 a > d 時為真。

seg &< segboolean

第一個 seg 是否不延伸到第二個 seg 的右邊?[a, b] &< [c, d] 當 b <= d 時為真。

seg &> segboolean

第一個 seg 是否不延伸到第二個 seg 的左邊?[a, b] &> [c, d] 當 a >= c 時為真。

seg = segboolean

兩個 seg 相等嗎?

seg && segboolean

兩個 seg 是否重疊?

seg @> segboolean

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

seg <@ segboolean

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


除了上述運算子之外,對於 seg 型別,還可以使用 表 9.1 中顯示的常規比較運算子。這些運算子首先比較 (a) 和 (c),如果它們相等,則比較 (b) 和 (d)。這使得在大多數情況下都可以進行相當好的排序,這在您希望對此型別使用 ORDER BY 時非常有用。

F.39.5. 注意事項 #

有關用法示例,請參閱迴歸測試 sql/seg.sql

(+-) 轉換為常規範圍的機制在確定邊界的有效數字位數方面並不完全準確。例如,如果生成的區間包含一個數量級,它會在下界增加一個額外的數字。

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

R-tree 索引的效能在很大程度上可能取決於輸入值的初始順序。對 seg 列上的輸入表進行排序可能非常有益;有關示例,請參閱指令碼 sort-segments.pl

F.39.6. 致謝 #

原始作者:Gene Selkov, Jr. ,阿貢國家實驗室數學與計算機科學部。

我主要感謝 Joe Hellerstein 教授(https://dsf.berkeley.edu/jmh/),他闡明瞭 GiST(http://gist.cs.berkeley.edu/)的要點。我還要感謝所有過去和現在的 Postgres 開發者,是他們使我能夠創造自己的世界並安寧地生活在其中。我想感謝阿貢實驗室和美國能源部多年來對我的資料庫研究的忠實支援。

提交更正

如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步澄清的內容,請使用 此表單 報告文件問題。