Cube
From PostgreSQL 中文维基, PostgreSQL 中文站, PostgreSQL 中国社区, PostgreSQL Chinese community
[编辑] cube
这个模块实现了一个叫 cube 的数据类型,用于表现多维的方块。
[编辑] 语法
下面是 cube 类型合法的外部表现形式。x, y, 等是浮点数:
| x | 一个一维点(或者,零长一维间隔) |
| (x) | 和上面相同 |
| x1,x2,...,xn | 一个在 n-维空间中的点,在内部代表一个零容积的n-维空间 |
| (x1,x2,...,xn) | 和上面相同 |
| (x),(y) | 一个一维的间隔,从 x 开始,于 y 终止;或者反过来,顺序无关 |
| [(x),(y)] | 和上面相同 |
| (x1,...,xn),(y1,...,yn) | 一个 n 维空间是用其对角点表示的 |
| [(x1,...,xn),(y1,...,yn)] | 和上面相同 |
n-维体定义和对角点的输入顺序无关的。cube 函数在需要的时候自动交换两个对角点,在内部保持一致的“左下角-右上角”的表现形式。
空白会被忽略,因此 [(x),(y)] 等效于 [ ( x ), ( y ) ]。
[编辑] 精度
数值在内部是用 64 位的浮点数存储的。这就意味着超过 16 位有效位的数值都会被截断。
[编辑] 使用
cube 模块包括一个用于 cube 数值的 GiST 索引操作符。GiST 操作符表支持的操作符包括:
- a = b 等于
- cube a 和 b 相等。
- a && b 重叠
- cube a 和 b 重叠
- a @> b 包含
- cube a 包含 cube b。
- a <@ b 包含于
- cube a 包含在 cube b 内部
(在 PostgreSQL 8.2 之前,包含操作符 @> 和 <@ 分别叫 @ 和 ~。这些名字仍然可用,但是已经废弃了,并最终会退休。请注意老名字保留下来是为了遵循以前依据核心的几何数据类型命名的传统!)
还提供了标准的 B-tree 操作符,比如
[a, b] < [c, d] Less than [a, b] > [c, d] Greater than
这些操作符除了排序之外没有实际的用途。这些操作符首先拿 (a) 和 (c) 比较,如果相同,则再比较 (b) 和 (d)。这样在大多数场合下都生成足够合理的排序结果,这样的话,在这个类型上使用 ORDER BY 就也是可以的了。
有下列函数可用:
| cube(float8) returns cube | 制作一个一维空间,两个坐标都相同。 cube(1) == '(1)' |
| cube(float8, float8) returns cube | 制作一个一维空间。cube(1,2) == '(1),(2)' |
| cube(float8[]) returns cube | 使用数组定义的坐标制作一个零容积的空间。cube(ARRAY[1,2]) == '(1,2)' |
| cube(float8[], float8[]) returns cube | 制作一个由两个输入的数组分别定义左下角和右上角坐标的空间。cube('{1,2}'::float[], '{3,4}'::float[]) == '(1,2),(3,4)' |
| cube(cube, float8) returns cube | 通过给一个现有的空间增加一个维度制作一个新空间,增加维度的方法是给原有的坐标增加同样的一个新坐标。这个功能可以用于从计算得出的数值一部分一部分地制作空间。cube('(1)',2) == '(1,2),(1,2)' |
| cube(cube, float8, float8) returns cube | 通过给一个现有空间添加一个维度来制作新的空间。这个功能可以用于从计算得出的数值一部分一部分地制作空间。cube('(1,2)',3,4) == '(1,3),(2,4)' |
| cube_dim(cube) returns int | 返回空间的维数 |
| cube_ll_coord(cube, int) returns double | 返回一个空间左下角的第 n 个坐标值 |
| cube_ur_coord(cube, int) returns double | 返回一个空间右上角的第 n 个坐标值 |
| cube_is_point(cube) returns bool | 如果空间是一个点,也就是说,定义的两个角是一样的,则返回真。 |
| cube_distance(cube, cube) returns double | 返回两个空间之间的距离。如果俩空间都是点,那么就是普通的距离函数。 |
| cube_subset(cube, int[]) returns cube | 从一个现有的空间上制作一个新空间,使用来自一个数组下标的列表制作新的坐标。可以用于寻找一个维的LL和UR坐标,比如, 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) returns cube | 制作两个空间的联合 |
| cube_inter(cube, cube) returns cube | 制作两个空间的交 |
| cube_enlarge(cube c, double r, int n) returns cube | 通过指定在至少 n 维内的半径来增加空间的体积。如果半径是负数,那么空间会收缩。这个功能可以用于在某点周围创建一个范围空间,用于搜索附近的电。所有预定义的维度都会被半径 r 修改。LL坐标被 r 减小,UR坐标被 r 增大。如果一个 LL 坐标缩小得比对应的 UR 坐标还要大(发生在 r < 0的场合),那么两个坐标都设置为它们的平均值。如果 n 大于预定义的维数,并且空间已经增大到大于 0 (r >= 0),那么就用 0 做为额外的坐标的基数。 |
[编辑] 缺省
我相信这个联合:
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)
在不同维数的空间上的所有二元操作上,我假设了低维度的那个空间是一个迪卡尔映射,也就是说,在字串表示形式里头会在省略的坐标上用0表示,上面的例子等效于:
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)
[编辑] 备注
使用例子可以参考回归测试的 sql/cube.sql。
为了避免人们犯错,在空间的维数上有个 100 的上限。如果你需要更大的,可以在 cubedata.h 里头设置。
[编辑] 致谢
原作者: Gene Selkov, Jr. <selkovjr@mcs.anl.gov>, Mathematics and Computer Science Division, Argonne National Laboratory.
感谢 Joe Hellerstein 教授( http://db.cs.berkeley.edu/~jmh/ )教我使用 GiST 的 gist( http://gist.cs.berkeley.edu/ ),并且感谢 Joe 的前学生 Andy Dong ( http://best.me.berkeley.edu/~adong/ ),因为他为 Illustra 写了很好的例子,http://garcia.me.berkeley.edu/~adong/rtree 。我还特别感谢 Postgres 开发人员,不管是现在还是过去,帮助我创建了我自己的世界,并且在其中不受干扰地生活。我还要衷心感谢阿拉贡实验室(Argonne Lab)和美国能源部这些年来对我的数据库研究的坚定支持。
Bruno Wolff III <bruno@wolff.to> 在 2002 年的八/九月对这个包作出了小型的维护。包括把单精度修改为双精度,并且增加了一些新的函数。
还有一些更新来自 Joshua Reich <josh@root.net>,他是在 2006 年七月做的改进。包括 cube(float8[], float8[]) 和清理代码,使之使用 V1 的调用协议取代 V0 的协议。
