PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

F.10. cube — 多维立方体数据类型 #

F.10.1. 语法
F.10.2. 精度
F.10.3. 用法
F.10.4. 默认值
F.10.5. 注记
F.10.6. 致谢

该模块实现数据类型 cube,用于表示多维立方体。

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

F.10.1. 语法 #

Table F.1 展示了 cube 类型的有效外部表示。x、y 等表示浮点数。

Table F.1. Cube 外部表示

外部语法含义
x一个一维点(或零长度的一维区间)
(x)同上
x1,x2,...,xnn 维空间中的一个点,内部表示为零体积立方体
(x1,x2,...,xn)同上
(x),(y)从 x 到 y(或相反)的一维区间;顺序无关紧要
[(x),(y)]同上
(x1,...,xn),(y1,...,yn)由一对对角顶点表示的 n 维立方体
[(x1,...,xn),(y1,...,yn)]同上

立方体对角顶点以何种顺序输入无关紧要。cube 函数会在需要时自动交换值,以创建统一的“左下 — 右上”内部表示。当顶点重合时,cube 只存储一个顶点并附加一个“是点”标志,以避免浪费空间。

输入时忽略空白,因此 [(x),(y)] 与 [ ( x ), ( y ) ] 相同。

F.10.2. 精度 #

值在内部存储为 64 位浮点数。这意味着有效数字超过约 16 位的数字会被截断。

F.10.3. 用法 #

Table F.2 展示了为 cube 类型提供的专用操作符。

Table F.2. Cube 操作符

操作符

描述

cube && cube → boolean

立方体是否重叠?

cube @> cube → boolean

第一个立方体是否包含第二个?

cube <@ cube → boolean

第一个立方体是否包含于第二个?

cube -> integer → float8

提取立方体的第 n 个坐标(从 1 开始计数)。

cube ~> integer → float8

按以下方式提取立方体的第 n 个坐标:n = 2 * k - 1 表示第 k 维的下界,n = 2 * k 表示第 k 维的上界。负的 n 表示相应正坐标的取反值。该操作符专为 KNN-GiST 支持设计。

cube <-> cube → float8

计算两个立方体之间的欧几里得距离。

cube <#> cube → float8

计算两个立方体之间的曼哈顿(L-1 度量)距离。

cube <=> cube → float8

计算两个立方体之间的切比雪夫(L-inf 度量)距离。


除上述操作符外,Table 9.1 中所示的常规比较操作符也适用于 cube 类型。这些操作符先比较第一个坐标,如果相等再比较第二个坐标,依此类推。它们的存在主要是为了支持 cube 的 B 树索引操作符类,例如想在 cube 列上建立 UNIQUE 约束时这可能有用。除此之外,这种排序没有太多实际用处。

cube 模块还为 cube 值提供 GiST 索引操作符类。cube GiST 索引可用于在 WHERE 子句中使用 =、&&、@> 与 <@ 操作符搜索值。

此外,cube GiST 索引还可在 ORDER BY 子句中使用度量操作符 <->、<#> 与 <=> 查找最近邻。例如,可以这样高效地找到三维点 (0.5, 0.5, 0.5) 的最近邻:

SELECT c FROM test ORDER BY c <-> cube(array[0.5,0.5,0.5]) LIMIT 1;

~> 操作符也可以这样使用,高效地检索按选定坐标排序的前几个值。例如,要获取按第一个坐标(左下角)升序排列的前几个立方体,可以使用以下查询:

SELECT c FROM test ORDER BY c ~> 1 LIMIT 5;

要获取按右上角第一个坐标降序排列的二维立方体:

SELECT c FROM test ORDER BY c ~> 3 DESC LIMIT 5;

Table F.3 展示了可用的函数。

Table F.3. Cube 函数

函数

描述

示例

cube ( float8 ) → cube

构造两个坐标相同的一维立方体。

cube(1) → (1)

cube ( float8, float8 ) → cube

构造一维立方体。

cube(1, 2) → (1),(2)

cube ( float8[] ) → cube

使用数组定义的坐标构造零体积立方体。

cube(ARRAY[1,2,3]) → (1, 2, 3)

cube ( float8[], float8[] ) → cube

用两个数组定义的右上与左下坐标构造立方体,两个数组必须长度相同。

cube(ARRAY[1,2], ARRAY[3,4]) → (1, 2),(3, 4)

cube ( cube, float8 ) → cube

通过在现有立方体上增加一个维度构造新立方体,新坐标的两个端点取相同值。这适合用计算出的值逐步构建立方体。

cube('(1,2),(3,4)'::cube, 5) → (1, 2, 5),(3, 4, 5)

cube ( cube, float8, float8 ) → cube

通过在现有立方体上增加一个维度构造新立方体。这适合用计算出的值逐步构建立方体。

cube('(1,2),(3,4)'::cube, 5, 6) → (1, 2, 5),(3, 4, 6)

cube_dim ( cube ) → integer

返回立方体的维数。

cube_dim('(1,2),(3,4)') → 2

cube_ll_coord ( cube, integer ) → float8

返回立方体左下角的第 n 个坐标值。

cube_ll_coord('(1,2),(3,4)', 2) → 2

cube_ur_coord ( cube, integer ) → float8

返回立方体右上角的第 n 个坐标值。

cube_ur_coord('(1,2),(3,4)', 2) → 4

cube_is_point ( cube ) → boolean

如果立方体是一个点(即两个定义顶点相同)则返回真。

cube_is_point(cube(1,1)) → t

cube_distance ( cube, cube ) → float8

返回两个立方体之间的距离。如果两个立方体都是点,这就是普通的距离函数。

cube_distance('(1,2)', '(3,4)') → 2.8284271247461903

cube_subset ( cube, integer[] ) → cube

使用数组给出的维度索引列表,从现有立方体构造新立方体。可用于提取单个维度的端点、删除维度,或按需重排维度。

cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[2]) → (3),(7)

cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]) → (5, 3, 1, 1),(8, 7, 6, 6)

cube_union ( cube, cube ) → cube

产生两个立方体的并集。

cube_union('(1,2)', '(3,4)') → (1, 2),(3, 4)

cube_inter ( cube, cube ) → cube

产生两个立方体的交集。

cube_inter('(1,2)', '(3,4)') → (3, 4),(1, 2)

cube_enlarge ( c cube, r double, n integer ) → cube

将立方体的大小在至少 n 个维度上按指定半径 r 扩大。半径为负时改为收缩立方体。所有已定义的维度都按半径 r 改变:左下坐标减小 r,右上坐标增大 r。如果某个左下坐标被增大到超过相应的右上坐标(这只会发生在 r < 0 时),则两个坐标都被设为它们的平均值。如果 n 大于已定义维数,并且立方体正在被扩大(r > 0),则添加额外维度使总数达到 n;额外坐标以 0 作为初始值。该函数适合在某个点周围创建用于搜索邻近点的边界框。

cube_enlarge('(1,2),(3,4)', 0.5, 3) → (0.5, 1.5, -0.5),(3.5, 4.5, 0.5)


F.10.4. 默认值 #

下面这个并集:

select cube_union('(0,5,2),(2,3,1)', '0');
cube_union
-------------------
(0, 0, 0),(2, 5, 2)
(1 row)

并不违反常识,下面的交集也一样:

select cube_inter('(0,-1),(1,1)', '(-2),(2)');
cube_inter
-------------
(0, 0),(1, 0)
(1 row)

在对维数不同的立方体执行的所有二元运算中,较低维的那个被假定为一个笛卡尔投影,即在字符串表示中省略的坐标以零代替。上面的例子等效于:

cube_union('(0,5,2),(2,3,1)','(0,0,0),(0,0,0)');
cube_inter('(0,-1),(1,1)','(-2,0),(2,0)');

下面的包含谓词使用点语法,而实际上第二个参数内部由一个箱体表示。这种语法使得为(box,point)谓词定义单独的点类型与函数变得没有必要。

select cube_contains('(0,0),(1,1)', '0.5,0.5');
cube_contains
--------------
t
(1 row)

F.10.5. 注记 #

用法示例请参见回归测试 sql/cube.sql。

为了让人们更难把事情搞坏,立方体的维数上限为 100。如果你需要更大,可以在 cubedata.h 中修改此设置。

F.10.6. 致谢 #

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

我首先要感谢 Joe Hellerstein 教授(https://dsf.berkeley.edu/jmh/)阐明了 GiST(http://gist.cs.berkeley.edu/)的精髓,并感谢他以前的学生 Andy Dong 为 Illustra 编写的示例。我也要感谢过去与现在的所有 Postgres 开发者,让我能够创造自己的世界并安然居于其中。同时我感谢阿贡实验室与美国能源部多年来对我数据库研究的坚定支持。

Bruno Wolff III 于 2002 年 8/9 月对该扩展包进行了少量更新,包括把精度从单精度改为双精度,并新增了一些函数。

Joshua Reich 于 2006 年 7 月进行了更多更新,包括 cube(float8[], float8[]),以及将代码改为使用 V1 调用协议取代已弃用的 V0 协议。