ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [,...]
有人可以给我一些例子如何使用USING运算符?是否可以获得结果集的交替顺序?
> SELECT * FROM tab ORDER BY col USING <
但这是无聊,因为这是没有什么你不能得到与传统的ORDER BY col ASC。
此外,标准目录没有提到任何令人兴奋的奇怪的比较函数/运算符。你可以得到他们的列表:
> SELECT amoplefttype::regtype,amoprighttype::regtype,amopopr::regoper FROM pg_am JOIN pg_amop ON pg_am.oid = pg_amop.amopmethod WHERE amname = 'btree' AND amopstrategy IN (1,5);
你会注意到,和>原始类型的函数,如整数,日期等,一些更多的数组和向量等。这些运算符都不会帮助您获得自定义排序。
在大多数情况下,需要定制排序,你可以使用类似的东西… ORDER BY somefunc(tablecolumn)… wherefunc适当地映射值。因为它适用于每个数据库,这也是最常见的方式。对于简单的事情,你甚至可以写一个表达式而不是自定义函数。
开关齿轮
ORDER BY … USING在以下情况下有意义:
>排序是如此罕见,somefunc技巧不工作。
>您使用非原始类型(如点,圆或虚数),并且不想在查询中使用奇怪的计算重复自己。
>您要排序的数据集太大,需要或甚至需要索引支持。
我将专注于复杂的数据类型:通常有多种方式以合理的方式对它们进行排序。一个很好的例子是point:你可以通过到(0,0)的距离,或者x先,然后y或者y或你想要的任何其他东西来“排序”他们。
当然,Postgresql有预定义的运算符:
> CREATE TABLE p ( p point ); > SELECT p <-> point(0,0) FROM p;
但是没有一个被声明为可用于ORDER BY默认情况下(见上文):
> SELECT * FROM p ORDER BY p; ERROR: could not identify an ordering operator for type point TIP: Use an explicit ordering operator or modify the query.
点的简单运算符是“下面”和“上面”运算符< ^和> ^。他们只是简单地比较点的y部分。但:
> SELECT * FROM p ORDER BY p USING >^; ERROR: operator > is not a valid ordering operator TIP: Ordering operators must be "<" or ">" members of __btree__ operator families.
ORDER BY USING需要一个具有定义语义的运算符:显然它必须是一个二进制运算符,它必须接受与参数相同的类型,并且必须返回boolean。我认为它也必须是可传递的(如果a< b和b< c,那么a< c)。可能有更多的要求。但是所有这些要求对于正确的btree-index排序也是必要的。这解释了包含对btree的引用的奇怪的错误消息。 ORDER BY USING还不仅需要定义一个运算符,还需要运算符类和运算符族。虽然可以实现只有一个操作符排序,Postgresql尝试有效排序和最小化比较。因此,即使你只指定一个操作符,其他操作符也必须遵守某些数学约束 – 我已经提到了传输性,但还有更多。 开关Gears 让我们定义一些合适的:一个运算符,它只比较y部分。 第一步是创建一个可以由btree索引访问方法使用的自定义操作符系列。 see
> CREATE OPERATOR FAMILY xyzfam USING btree; -- superuser access required! CREATE OPERATOR FAMILY
接下来,我们必须提供一个比较器函数,当比较两个点时返回-1,1。此函数将在内部调用!
> CREATE FUNCTION xyz_v_cmp(p1 point,p2 point) RETURNS int AS $$BEGIN RETURN btfloat8cmp(p1[1],p2[1]); END $$ LANGUAGE plpgsql; CREATE FUNCTION
接下来,我们为该系列定义运算符类。 See the manual的数字说明。
> CREATE OPERATOR CLASS xyz_ops FOR TYPE point USING btree FAMILY xyzfam AS OPERATOR 1 <^,OPERATOR 3 ?-,OPERATOR 5 >^,FUNCTION 1 xyz_v_cmp(point,point) ; CREATE OPERATOR CLASS
此步骤组合了多个运算符和函数,并定义了它们的关系和含义。例如OPERATOR 1表示:这是小于测试的运算符。
现在运算符< ^和'> ^’可以用于ORDER BY USING:
> INSERT INTO p SELECT point(floor(random()*100),floor(random()*100)) FROM generate_series(1,5); INSERT 0 5 > SELECT * FROM p ORDER BY p USING >^; p --------- (17,8) (74,57) (59,65) (0,87) (58,91)
Voila – 按y排序。
总结:ORDER BY … USING是一个有趣的外观下的Postgresql。但是没有什么你会需要很快,除非你在非常具体的数据库技术领域工作。
另一个示例可以找到in the Postgres docs.,其源代码为示例here和here.此示例还显示了如何创建运算符。