聚合函数#

聚合函数允许您通过跨行组执行计算来汇总数据。例如,如果您有一个 orders 表中有一个 amount 列,则可以使用聚合函数来获取 amount 列,或者用于所有行,或者用于共享特定值的每组行,例如共享相同值的所有行 order_date

备注

聚合函数包括 disabled 默认情况下,在PostgREST中,如果没有适当的保护措施,聚合函数可能会产生性能问题。看见 数据库-已启用聚合 了解更多细节。

PostgREST支持以下聚合函数: avg()count()max()min() ,以及 sum() 。请参阅 section on aggregate functions in the PostgreSQL documentation 有关这些功能的详细说明,请参阅。

若要使用聚合函数,请将该函数追加到 select 参数,如下所示:

curl "http://localhost:3000/orders?select=amount.sum()"

使用上述查询,PostgREST将返回单行和名为的单列 sum 中的所有值的总和。 amount 专栏:

[
  {
    "sum": 1234.56
  }
]

只需将更多具有聚合函数的列添加到 select 参数。

要按其他列分组,只需将这些列添加到 select 参数。例如:

curl "http://localhost:3000/orders?select=amount.sum(),amount.avg(),order_date"

中的每个唯一值返回一行。 order_date 列,其中包含 amount 列,用于共享相同的所有行 order_date

[
  {
    "sum": 1234.56,
    "avg": 123.45,
    "order_date": "2023-01-01"
  },
  {
    "sum": 2345.67,
    "avg": 234.56,
    "order_date": "2023-01-02"
  }
]

备注

聚合函数与其他PostgREST功能配合使用,如 水平滤波JSON列 ,以及 有序化 。请注意,目前聚合函数与 域表示法 。此外,PostgreSQL的 HAVING 子句和按聚合列排序尚不受支持。

的案例 count()#

备注

在添加聚合函数之前,可以通过添加 count (不带括号)到 select 参数。虽然仍支持此功能,但将来可能会弃用此功能,因此使用此传统功能 not recommended. 请使用 count() (带括号)。

count() 被特殊处理,因为它可以在没有关联列的情况下使用。以下面的查询为例:

curl "http://localhost:3000/orders?select=count(),order_date"

中的每个唯一值返回一行 order_date 列,具有共享相同的所有行的计数 order_date

[
  {
    "count": 4,
    "order_date": "2023-01-01"
  },
  {
    "count": 2,
    "order_date": "2023-01-02"
  }
]

什么时候 count() 与关联列一起使用时,其行为略有不同:它将返回不是 NULL 。这是由于PostgreSQL本身如何实现 count() 功能。

更名和选角#

重命名聚合#

与其他列一样,您也可以重命名聚合列。看见 重命名列 了解更多细节。

重命名列在聚合函数的上下文中特别有用,因为默认情况下,应用了聚合函数的列将使用应用的聚合函数的名称。在使用同一类型的多个聚合函数时,您可能希望提供一个语义上更有意义的名称或防止冲突。

浇注骨料#

将聚合函数应用于列时,可以将输入的值强制转换为聚合函数 and 聚合函数的输出值。在这两种情况下,语法的工作原理均如中所述 铸造柱 ,唯一的区别是演员阵容的安排。

对输入值进行强制转换#

例如,假设 orders 表有一个JSON列, order_details ,并且该列包含一个JSON对象,该对象具有一个键, tax_amount 。假设您想要获得每个订单的税额总和。您可以使用 ->->> 运算符使用该键提取值(请参见 JSON列 ),但这些运算符将返回JSON和 text ,并且这两种类型都不能与 sum()

因此,您需要首先将输入值转换为与兼容的类型 sum() (例如: numeric )。强制转换输入值的方式与强制转换任何其他值的方式完全相同:

curl "http://localhost:3000/orders?select=order_details->tax_amount::numeric.sum()"

有了这个,你将得到施法人员的总和。 tax_amount 值:

[
  {
    "sum": 1234.56
  }
]

对输出的值进行转换#

现在让我们回到一个涉及 amount 专栏中的 orders 桌子。想象一下,我们想要获得 amount 纵队。实现此目的的一种方法是使用 avg() 聚合函数,然后将该函数的输出值强制转换为 int 。要强制转换函数的输出值,我们只需将强制转换 after 聚合函数:

curl "http://localhost:3000/orders?select=amount.avg()::int"

然后,您将收到四舍五入的平均值作为结果:

[
  {
    "avg": 201
  }
]

当然,如果您愿意,可以同时使用输入和输出强制转换。

将聚合函数与资源嵌入一起使用#

聚合函数可以与一起使用 资源嵌入 。您可以将嵌入资源用作分组列,在嵌入资源的上下文中使用聚合函数,或将分散资源中的列用作分组列或聚合函数的输入。

将嵌入的资源用作分组列#

通过将嵌入资源用作分组列,您可以使用关联中的数据对聚合结果进行分组。

例如,假设 orders 上例中的表与 customers 桌子。如果您想要得到 amount 列按 name 列中的 customers 表中,您可以使用标准的 资源嵌入 语法,并对 amount 纵队。

curl "http://localhost:3000/orders?select=amount.sum(),customers(name)"

然后,您将获得合计金额以及嵌入的客户资源:

[
  {
    "sum": 100,
    "customers": {
      "name": "Customer A"
    }
  },
  {
    "sum": 200,
    "customers": {
      "name": "Customer B"
    }
  }
]

备注

前面的示例使用Has-One关联来演示此功能,但您也可以使用Has-More关联作为分组列,尽管这样做没有什么明显的用例。

在嵌入资源的上下文中使用聚合函数#

嵌入资源时,可以对关联资源中的列应用聚合函数,以在嵌入资源的上下文中执行聚合。

继续以下示例关系: orderscustomers 在上一节中,假设您想要获取 namecity ,以及 state 对于每个客户,以及按订单日期分组的客户订单金额总和。这可以通过以下方式完成:

curl "http://localhost:3000/customers?select=name,city,state,orders(amount.sum(),order_date)"
[
  {
    "name": "Customer A",
    "city": "New York",
    "state": "NY",
    "orders": [
      {
        "sum": 215.22,
        "order_date": "2023-09-01"
      },
      {
        "sum": 905.73,
        "order_date": "2023-09-02"
      }
    ]
  },
  {
    "name": "Customer B",
    "city": "Los Angeles",
    "state": "CA",
    "orders": [
      {
        "sum": 329.71,
        "order_date": "2023-09-01"
      },
      {
        "sum": 425.87,
        "order_date": "2023-09-03"
      }
    ]
  }
]

In this example, the amount column is summed and grouped by the order_date within the context of the embedded resource. That is, the name, city, and state from the customers table have no bearing on the aggregation performed in the context of the orders association; instead, each aggregation can be seen as being performed independently on just the orders belonging to a particular customer, using only the data from the embedded resource for both grouping and aggregation.

使用分散资源中的列#

当你 spread an embedded resource ,则将展开的资源中的列视为顶级资源的列,无论是将它们用作分组列还是将聚合函数应用于它们。

对分散的资源中的列进行分组#

例如,假设您想要将 amount 列中的 orders 表,使用 citystate 中的列 customers 表作为分组列。要实现这一点,可以从 customers 表并展开它们;然后将它们用作分组列:

curl "http://localhost:3000/orders?select=amount.sum(),...customers(city,state)

结果将会是一样的 citystate 都是来自 orders 表:

[
  {
    "sum": 2000.29,
    "city": "New York",
    "state": "NY"
  },
  {
    "sum": 9241.21,
    "city": "Los Angeles",
    "state": "CA"
  }
]

使用分散的资源中的列聚合函数#

现在想象一下, customers 表中有一个 joined_date 列,该列表示客户加入的日期。您希望同时获得最新版本和最旧版本 joined_date 适用于在每个不同的订单日期下订单的客户。这可以表达为:

curl "http://localhost:3000/orders?select=order_date,...customers(joined_date.max(),joined_date.min())

由于分散资源中的列被视为顶级资源中的列,因此 max()min() 都适用于 within 顶层的上下文,而不是像上一节那样在嵌入资源的上下文中。

结果将与将聚合应用于顶级列的结果相同:

[
  {
    "order_date": "2023-11-01",
    "max": "2023-10-15",
    "min": "2013-10-01"
  },
  {
    "order_date": "2023-11-02",
    "max": "2023-10-30",
    "min": "2016-02-11"
  }
]