聚合函数#
聚合函数允许您通过跨行组执行计算来汇总数据。例如,如果您有一个 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关联作为分组列,尽管这样做没有什么明显的用例。
在嵌入资源的上下文中使用聚合函数#
嵌入资源时,可以对关联资源中的列应用聚合函数,以在嵌入资源的上下文中执行聚合。
继续以下示例关系: orders
和 customers
在上一节中,假设您想要获取 name
, city
,以及 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
表,使用 city
和 state
中的列 customers
表作为分组列。要实现这一点,可以从 customers
表并展开它们;然后将它们用作分组列:
curl "http://localhost:3000/orders?select=amount.sum(),...customers(city,state)
结果将会是一样的 city
和 state
都是来自 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"
}
]