加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在PostgreSQL中的“ORDER BY … USING”子句

发布时间:2020-12-13 16:45:49 所属栏目:百科 来源:网络整理
导读:ORDER BY子句在PostgreSQL文档中描述为: ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [,...] 有人可以给我一些例子如何使用USING运算符?是否可以获得结果集的交替顺序? 一个非常简单的例子是: SELECT * FROM tab O
ORDER BY子句在PostgreSQL文档中描述为:
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.此示例还显示了如何创建运算符。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读