QuickQuery: contar, sumar y agrupar en una línea
Referencia de QuickQuery en el SDK .NET: seis métodos sobre IAQuery para contar, sumar, agrupar y consultar secciones con valores ya convertidos.
QuickQuery responde las preguntas de siempre (cuántos hay, cuánto suman, cuáles son) sin construir un IAQueryRequestParameters. Vive en el propio cliente y devuelve el valor convertido a su tipo:
using static DemoUp.MyDinaup.SectionsD; // constantes de tu MyDinaup
// ¿Cuánto he facturado este mes? Un decimal
var facturado = await dinaupClient.QuickQuery.SumAsync(
VentasIngresosD._SectionID,
VentasIngresosD.VentasIngresosES.ImporteTotal,
[QuickQueryFilter.GreaterThanOrEqual(VentasIngresosD.VentasIngresosES.FechaOperacion, "2026-07-01")]);
// ¿Cuántas facturas llevo? Un int
var cuantas = await dinaupClient.QuickQuery.CountAsync(
VentasIngresosD._SectionID,
[QuickQueryFilter.GreaterThanOrEqual(VentasIngresosD.VentasIngresosES.FechaOperacion, "2026-07-01")]);Cada llamada es una consulta IAQuery por debajo: la agregación corre en la base de datos y heredas sus permisos y límites tal cual.
Seis métodos, seis preguntas
| Método | Responde a | Devuelve |
|---|---|---|
CountAsync(seccion, filtros?) | cuántas filas cumplen | int |
SumAsync(seccion, campo, filtros?) | cuánto suma un campo | decimal |
ValuesAsync(seccion, campo, filtros?, orden?, limite?) | los valores de una columna | List<string> |
FirstAsync(seccion, campos, filtros?, orden?) | la primera fila que cumple | Dictionary<string, string> o null |
QueryAsync(seccion, campos, filtros?, orden?, limite?, pagina?) | las filas completas | QuickQueryResult |
GroupByAsync(seccion, campoGrupo, agregaciones, filtros?, orden?, limite?) | totales por grupo | QuickQueryResult |
Todos los parámetros con ? son opcionales. orden es un texto tipo "campo desc" (sin dirección: asc en consultas, desc en agrupadas) y solo admite campos presentes en el SELECT. limite va de 1 a 30.000 filas (100 si no lo indicas) y pagina empieza en 1: fuera de rango, el SDK lanza la excepción antes de llamar al servidor (mismas validaciones que IAQuery).
Los campos aceptan las mismas rutas que IAQuery, incluidas las de secciones relacionadas de cuatro tramos.
Filtros que se leen como frases
QuickQueryFilter trae un constructor estático por operador: Equal, NotEqual, GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual, Like, In. Un rango son dos filtros:
QuickQueryFilter[] julio =
[
QuickQueryFilter.GreaterThanOrEqual(VentasIngresosD.VentasIngresosES.FechaOperacion, "2026-07-01"),
QuickQueryFilter.LessThanOrEqual(VentasIngresosD.VentasIngresosES.FechaOperacion, "2026-07-31")
];- Los filtros se combinan con
and;.Or()cambia el conector de ese filtro:QuickQueryFilter.Equal(campo, "1").Or(). Likeno añade comodines: inclúyelos tú (%texto%).Inrecibe los valores separados por comas ("a,b,c").- Para otro operador (
is null,not in...), construye el objeto a mano:new QuickQueryFilter { Field = campo, Op = "is null" }. Los operadores admitidos son los de IAQuery. - Los valores viajan como texto: fechas en ISO (
2026-07-31), números con punto decimal, booleanos como1y0.
Agrupar con GroupByAsync
GroupByAsync agrupa por un campo y calcula una o varias agregaciones, definidas con QuickQueryAggField.Sum, .Count, .Avg, .Max o .Min:
// Diez clientes con más facturación
var res = await dinaupClient.QuickQuery.GroupByAsync(
VentasIngresosD._SectionID,
VentasIngresosD.VentasIngresosES.ReferenciaCliente,
[QuickQueryAggField.Sum(VentasIngresosD.VentasIngresosES.ImporteTotal)],
orderBy: VentasIngresosD.VentasIngresosES.ImporteTotal + " desc",
limit: 10);
foreach (var fila in res.Rows)
Console.WriteLine($"{fila[res.Columns[0]]}: {fila[res.Columns[1]]}");La primera columna es el valor del grupo; después, una por agregación. Para agrupar por una función de fecha (monthyear, quarter...), baja a IAQuery: QuickQuery agrupa solo por el valor directo del campo.
Leer el resultado
QueryAsync y GroupByAsync devuelven un QuickQueryResult:
| Campo | Contenido |
|---|---|
Ok | true si la consulta se ejecutó |
Error | detalle del fallo cuando Ok es false |
Rows | filas como List<Dictionary<string, string>> |
Columns | alias de las columnas, en el orden del SELECT |
Total | filas devueltas en esta página |
TimeMs | milisegundos de ejecución en el servidor |
Las claves de Rows son los alias por defecto de IAQuery: el último tramo de la ruta de cada campo. Con claves internas (pr_...) o rutas relacionadas, lee por posición con Columns, como en el ejemplo de arriba.
QuickQuery no lanza excepciones: el error llega en Ok y Error. CountAsync y SumAsync devuelven 0 tanto si el resultado es cero como si la consulta falló; si necesitas distinguirlo, usa QueryAsync y comprueba Ok.
Lo que hereda de IAQuery
- Los permisos del usuario de la sesión: sin permiso de consulta sobre la sección, la llamada se rechaza.
- El filtro
eliminado = 0, añadido por el servidor en toda consulta. - Los operadores, las validaciones de campo y el tope de 30.000 filas por página.
- Todos los valores llegan como texto: conviértelos a su tipo al leerlos.
Cuándo bajar a IAQuery
QuickQuery cubre el caso frecuente; el constructor completo sigue ahí para el resto:
- Agrupar por funciones de fecha (
month,quarter,monthyear...). - Filtrar sobre los agregados con
AddHaving. count*,countdistincto alias propios por columna.- Ver el SQL generado (
IAQueryResponse.SQL) mientras desarrollas.
La referencia completa del motor, con sus operadores, funciones y límites, en IAQuery.
IAQuery: consultas dinámicas sin informe
Referencia de IAQuery en el SDK .NET: campos, operadores, funciones de agregación y fecha, límites del servidor y formato de la respuesta.
Dinaup.Database
Accede a PostgreSQL desde .NET con PGClient, con lecturas tipadas, upsert y lectura por lotes sin boilerplate.