cube
这个模块实现了一种数据类型cube来表示多维立方体。
此模块被视为“trusted”,也就是说,它可以在当前数据库上具有 CREATE 权限的非超级用户安装。
1. 语法
表 C.2展示了cube类型有效的外部表示。x、y等表示浮点数。
表 C.2立方体外部表示
| 外部语法 | 含义 |
|---|---|
| x | 一个一维点(或者长度为零的一维区间) |
| (x) | 同上 |
| x1,x2,...,xn | n-维空间中的一个点,内部表示为一个零容积立方体 |
| (x1,x2,...,xn) | 同上 |
| (x),(y) | 开始于x并且结束于y的一个一维区间,反之亦然。顺序并不重要 |
| [(x),(y)] | 同上 |
| (x1,...,xn),(y1,...,yn) | 一个 n-维立方体,用它的对角顶点对表示 |
| [(x1,...,xn),(y1,...,yn)] | 同上 |
一个立方体的对角录入的顺序无关紧要。如果需要创建一种统一的“左下 — 右上”的内部表示,cube函数会自动地交换值。当角重合时,cube只存储一个角和一个“is point”标志,这样避免浪费空间。
输入中的空白空间会被忽略,因此[(x),(y)]与[ ( x ), ( y ) ]相同。
2. 精度
值在内部被存储为 64 位浮点数。这意味着超过 16 位有效位的数字将被截断。
3. 用法
表 C.3展示了为类型cube提供的专用的操作符。
表 C.3. 立方体操作符
| 操作符/描述 |
|---|
| 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 度量)距离。 |
这些操作符首先比较第一个坐标,如果它们相等再比较第二个坐标等等。 它们主要为支持cube的 b树索引操作符类而存在,这类操作符对支持cube列上的 UNIQUE 约束等很有用。否则,这种排序没有太大的实际作用。
cube模块也为cube值提供了一个 GiST 索引操作符类。cube GiST 索引可以被用于在WHERE子句中通过=、&&、@>以及<@操作符来搜索值。
此外,cube GiST 索引可以被用在ORDER BY子句中通过度量操作符<->、<#>和<=>来查找最近邻。例如,3-D 点(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;
以及得到通过右上角第一个坐标降序排列后的 2-D 立方体:
SELECT c FROM test ORDER BY c ~> 3 DESC LIMIT 5;
表 C.4展示了可用的函数。
表 C.4. 立方体函数
| 函数/描述/示例 |
|---|
| 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 用一个指定的半径r在至少n个维度上增加立方体的尺寸。如果该半径是负值,则该立方体会收缩。所有已定义的维度都会按照半径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) |
4. 默认值
下面的并:
test=## select cube_union('(0,5,2),(2,3,1)', '0');
cube_union
---------------------
(0, 0, 0),(2, 5, 2)
(1 row)
不会与常识矛盾,下面的交也不会
test=## 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)');
下列包含谓词使用点语法,不过实际上第二个参数在内部被表示为一个盒子。这种语法让我们不必定义一种单独的点类型以及用于谓词的函数。
test=## select cube_contains('(0,0),(1,1)', '0.5,0.5');
cube_contains
---------------
t
(1 row)
5. 注解
为了不容易出问题,对于立方体的维度数有 100 的限制。如果你想要更大的立方体,可以在cubedata.h中修改。