Agregaciones
Vincent Depassier · 29 de agosto de 2026
PraxQL — Agregaciones
PraxQL soporta GROUP BY, HAVING y funciones de agregación en el mismo cuerpo de consulta. No hay endpoint aparte ni función serverless que escribir.
Cuándo usarlas
Agregá cuando querés un número sobre un conjunto de filas y no las filas: ingresos por cliente, pedidos por estado, ticket promedio por región, el pedido más grande, la fecha más antigua.
Si querés las filas y el número, son dos consultas. Está al final.
Las cinco funciones
Función | Descripción |
| Cantidad de filas |
| Suma de valores numéricos |
| Promedio |
| Valor mínimo |
| Valor máximo |
Los nombres no distinguen mayúsculas. Cualquier cosa fuera de esta lista devuelve 400 INVALID_QUERY.
El select de una agregación
En una consulta de agregación cada elemento de select es un objeto, no un string suelto:
Campo | Obligatorio | Descripción |
| sí | Columna a agregar o por la que agrupar |
| no | Función de agregación. Omitila para una columna de dimensión. |
| no | Nombre de la columna resultante en la respuesta |
"select": [
{ "field": "Region", "alias": "Region" },
{ "field": "Total", "fn": "sum", "alias": "IngresoTotal" },
{ "field": "Id", "fn": "count", "alias": "CantidadPedidos" },
{ "field": "Total", "fn": "avg", "alias": "TicketPromedio" },
{ "field": "Total", "fn": "max", "alias": "PedidoMayor" }
]La misma columna puede aparecer varias veces con funciones distintas, como hace Total acá.
groupBy
Las columnas por las que agrupar. Todo elemento de select sin fn tiene que aparecer acá — es una regla de SQL, no de PraxQL, y romperla es la causa más común de una agregación rechazada.
"groupBy": ["Region"]having
Filtros aplicados después de agrupar. Misma sintaxis que where, más el campo fn para filtrar sobre un agregado:
"having": [
{ "field": "Total", "fn": "sum", "op": "gt", "value": 10000 }
]Ejemplo completo
Ingresos por región para pedidos posteriores a enero de 2026, dejando solo las regiones por encima de 10.000:
{
"refs": {
"Pedidos": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
},
"query": {
"from": "Pedidos",
"select": [
{ "field": "Region", "alias": "Region" },
{ "field": "Total", "fn": "sum", "alias": "IngresoTotal" },
{ "field": "Id", "fn": "count", "alias": "CantidadPedidos" },
{ "field": "Total", "fn": "avg", "alias": "TicketPromedio" }
],
"where": [
{ "field": "Fecha", "op": "gte", "value": "2026-01-01" }
],
"groupBy": ["Region"],
"having": [
{ "field": "Total", "fn": "sum", "op": "gt", "value": 10000 }
],
"orderBy": [
{ "field": "IngresoTotal", "dir": "desc" }
],
"limit": 20
}
}El orden en que pasan las cosas
FROM— elegir la tablaWHERE— filtrar filas individualesGROUP BY— agrupar lo que sobrevivióFunciones de agregación — calcular por grupo
HAVING— filtrar los gruposORDER BY— ordenarlosLIMIT/OFFSET— paginar
La consecuencia práctica: where filtra filas antes de agrupar, having filtra grupos después de agregar. "Regiones cuyos pedidos completados suman más de 10.000" es un where sobre el estado más un having sobre la suma — poner el estado en having hace otra pregunta, y en general no devuelve nada.
Permisos
Agregar necesita dos flags, y los dos vienen en `false` por defecto:
Flag | Dónde | Sin él |
| scope de tabla | cualquier |
| scope de columna | esa columna en particular no se puede agregar |
Así que una key recién creada no puede agregar nada hasta que lo habilites. Es a propósito: un agregado puede revelar la forma de datos que quien llama no tiene permitido leer fila por fila.
Agregaciones y relaciones
Los agregados no corren dentro de una subconsulta de relación. Podés agregar la tabla principal, o traer las filas relacionadas y agregarlas del lado del cliente.
Cuando necesitás totales y filas de detalle, mandá dos consultas. Son los mismos viajes que una consulta combinada habría costado internamente, y cada mitad queda cacheable por su cuenta.