【问题标题】:Postgres: Finding max value in an int array?Postgres:在 int 数组中查找最大值?
【发布时间】:2015-02-05 18:23:24
【问题描述】:

使用 Postgres 9.3...

有人能解释一下为什么我不能直接在未嵌套的数组上使用 max 函数吗?

据我了解,unnest 函数返回一个“setof”,就像 select 语句一样。那么为什么这个查询的简短版本不起作用呢? (我是在概念上遗漏了什么,还是我的问题与语法相关?)

table: foo_history: 

id | history::smallint
----------------------------------- 
1  |  {10,20,30,50,40}

这不起作用?

Select id, max(unnest(history)) as vMax from foo_history;

...但是这个可以...?

WITH foo as (
    select id, unnest(history) as history 
    from foo_history
)
Select 
    id, max(history) as vMax
From foo 
Group by id;

【问题讨论】:

  • 尽管我编写了自己的函数来解决问题,但我还是有点困惑。 'unnest' 函数返回一组行,而 max 函数对一组行进行操作。是有错误还是我没有得到什么?
  • 是的,有。 max 是一个聚合,因此它对每个元组的一个输入进行操作。它不能将集合作为这样的输入。要按照您描述的方式表达它,您可以使用子查询,例如select id, (select max(x) from unnest(history) x) as vmax from foo_history

标签: arrays postgresql max postgresql-9.3


【解决方案1】:

如果您安装 intarray 模块,它会提供一些额外的数组运算符,让您可以编写您想要的内容,尽管效率有些低:

CREATE EXTENSION intarray;

SELECT id, (sort_desc(history))[1] as vMax
FROM foo_history;

为数组编写最大和最小函数以添加到intarray 非常容易,代码非常简单。

否则你可以只写一个 SQL 函数:

CREATE OR REPLACE FUNCTION array_greatest(anyarray)
RETURNS anyelement
LANGUAGE SQL
AS $$
  SELECT max(elements) FROM unnest($1) elements
$$;

并使用它:

SELECT id, array_greatest(history) as vMax
FROM foo_history;

【讨论】:

  • 谢谢。就在写完这篇文章之后,我最终编写了自己的类似函数,该函数返回数组中最大值的位置。这并不是特别困难,但是,我对已经内置的所有其他功能感到惊讶,这种简单的功能还没有得到支持。
  • @user2259963 每个函数和实用程序都必须由某人编写,如果有人不想要它,它就不会被编写。在这个特殊的情况下,我很快会再试一次,自从上次尝试以来,我学到了很多关于 Pg 编码的知识,我希望看到它在核心中得到支持。
  • 我很欣赏别人看到的需要。让我知道我是否可以提供帮助。不幸的是,就我而言,我仍然不理解我认为的记录集和行集之间的根本区别。把一个记录集变成一个数组很容易——但反过来不行;如果我们采用另一种方式,现有聚合函数将支持数据。现在我正在研究一个函数来计算数组子集的标准偏差。 :)
  • 我得到:“SQL 错误 [42703]:错误:列“x”不存在其中:内联期间的 SQL 函数“array_greatest””。您需要在函数中的 unnest($1) 之后放置一个 x,否则它不起作用。
【解决方案2】:

在 PostgreSQL 9.6 和 8.4 中:

SELECT max(x) FROM unnest(ARRAY[1,2,80,3,15,4]) as x;

【讨论】:

  • 当我们达到 9.6 时,那就太好了!
【解决方案3】:

您必须记住,SQL 旨在对数据集进行操作。 MAX 函数在第一个示例中确实有效,只是没有按照您的预期工作。它将返回匹配的每一行的最大值。

group by 子句按预期工作,因为您现在聚合到一个集合中,然后从集合中获取最大值。 :)

【讨论】:

  • 当您考虑到可能有数百万条记录时,我的 2nd 示例似乎效率很低。有点倒退了……???在这种情况下,也许自定义函数是要走的路……
  • 根据您的评论,最大的功能应该可以工作,但这也不起作用。两个函数都返回...'错误:在不能接受集合的上下文中调用的集合值函数'
猜你喜欢
  • 1970-01-01
  • 2015-04-09
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 2020-08-20
  • 2015-02-03
  • 2012-08-14
相关资源
最近更新 更多