您是否能够为ORDER BY子句使用自定义Postgres比较函数?

时间:2010-09-11 16:04:57

标签: postgresql sorting

在Python中,我可以编写一个排序比较函数,它返回集合{-1, 0, 1}中的一个项目并将其传递给类似的排序函数:

sorted(["some","data","with","a","nonconventional","sort"], custom_function)

此代码将根据我在函数中定义的归类顺序对序列进行排序。

我可以在Postgres中做相同的操作吗?

e.g。

SELECT widget FROM items ORDER BY custom_function(widget)

编辑:欢迎提供文档示例和/或指示。

3 个答案:

答案 0 :(得分:13)

是的,你甚至可以创建一个功能索引来加速排序。

编辑:简单示例:

CREATE TABLE foo(
    id serial primary key,
    bar int
);
-- create some data
INSERT INTO foo(bar) SELECT i FROM generate_series(50,70) i;
-- show the result
SELECT * FROM foo;

CREATE OR REPLACE FUNCTION my_sort(int) RETURNS int 
LANGUAGE sql 
AS
$$
    SELECT $1 % 5; -- get the modulo (remainder)
$$;
-- lets sort!
SELECT *, my_sort(bar) FROM foo ORDER BY my_sort(bar) ASC;

-- make an index as well:
CREATE INDEX idx_my_sort ON foo ((my_sort(bar)));

本手册充满了如何使用自己的功能的例子,只是开始玩它。

答案 1 :(得分:0)

你可以做这样的事情

SELECT DISTINCT ON (interval_alias) *,
  to_timestamp(floor((extract('epoch' FROM index.created_at) / 10)) * 10) AT
  TIME ZONE 'UTC' AS interval_alias
  FROM index
  WHERE index.created_at >= '{start_date}'
  AND index.created_at <= '{end_date}'
  AND product = '{product_id}'
  GROUP BY id, interval_alias
ORDER BY interval_alias;

首先,您使用AS定义将作为订购列的参数。它可以是 function 或任何 SQL表达式。然后将其设置为ORDER BY表达式,您就完成了!

在我看来,这是进行这种排序的最顺畅的方式。

答案 2 :(得分:0)

我们可以避免对使用名称的ordering methods感到困惑:

    标准SQL select * from t order by f(x)子句的
  • “得分函数”
  • Python的sort数组方法的
  • “比较函数” (问题文本中的“ sort函数”)。

PostgreSQL的ORDER BY子句具有 3种机制进行排序:

  1. 使用“得分功能”的标准,也可以与INDEX一起使用。
  2. 特殊的“标准字符串比较替代项”,通过collation配置
    (仅适用于textvarchar等数据类型)。
  3. ORDER BY ... USING子句。请参阅this questiondocs example
    示例:SELECT * FROM mytable ORDER BY somecol USING ~<~,其中~<~是运算符,它嵌入了比较函数

也许RDBMS(作为PostgreSQL)中的“标准方式”与Python的标准不同,因为索引是RDBMS的目标,并且更容易对评分函数进行索引。

问题的答案:

  • 直接解决方案。 没有直接的方法将用户定义的函数用作比较函数,就像在Python或Javascript之类的 sort方法中一​​样。< / p>

  • 间接解决方案。您可以在用户定义的运算符中使用用户定义的比较函数,并使用用户定义的运算符类对其进行索引。请参见PostgreSQL文档:


解释比较函数

在Python中,比较功能如下所示:

def compare(a, b):
    return 1 if a > b else 0 if a == b else -1

比较功能得分功能 使用的CPU少。
得分函数未知的情况下表达命令也是有用的

请参阅完整的说明

其他典型比较功能

Wikipedia's example比较元组:

function tupleCompare((lefta, leftb, leftc), (righta, rightb, rightc))
    if lefta ≠ righta
        return compare(lefta, righta)
    else if leftb ≠ rightb
        return compare(leftb, rightb)
    else
        return compare(leftc, rightc)

在Java语言中:

function compare(a, b) {
  if (a is less than b by some ordering criterion) {
    return -1;
  }
  if (a is greater than b by the ordering criterion) {
    return 1;
  }
  // a must be equal to b
  return 0;
}

PostgreSQL docs的C ++示例:

complex_abs_cmp_internal(Complex *a, Complex *b)
{
    double      amag = Mag(a),
                bmag = Mag(b);

    if (amag < bmag)
        return -1;
    if (amag > bmag)
        return 1;
    return 0;
}