Salta ai contenuti

Raggruppamento e Aggregazioni

Archie Core offre potenti capacità di raggruppamento e aggregazione tramite la sua API GraphQL. Puoi raggruppare i record per valori di campo, calcolare funzioni di aggregazione (COUNT, SUM, AVG, MIN, MAX, COUNT_DISTINCT), filtrare i gruppi con condizioni HAVING e ordinare i risultati per valori aggregati.

Quando si utilizzano raggruppamento e aggregazioni, i seguenti argomenti sono disponibili su qualsiasi query di lista:

ArgomentoTipoDescrizione
groupBy[{TableName}GroupBy]Campi per raggruppare i risultati
aggregateBy[{TableName}AggregateInput]Funzioni di aggregazione da calcolare
having[{TableName}HavingFilterInput]Filtrare i gruppi per risultati aggregati
aggregateSort[{TableName}AggregateSortInput]Ordinare i risultati per valori aggregati

Questi argomenti possono essere combinati con argomenti standard come filter, first, skip e orderBy.

L’argomento groupBy accetta un array di valori enum che rappresentano i campi per cui raggruppare. I valori enum seguono il modello: il nome del campo in camelCase convertito in MAIUSCOLO.

Convenzione di denominazione:

Nome colonna (DB)Nome campo (GraphQL)Valore enum GroupBy
payment_methodpaymentMethodPAYMENTMETHOD
created_atcreatedAtCREATEDAT
statusstatusSTATUS
category_idcategoryIdCATEGORYID

Richiesta

query {
students(groupBy: [ISACTIVE]) {
items {
isActive
}
count
}
}

Risposta

{
"data": {
"students": {
"items": [
{ "isActive": true },
{ "isActive": false }
],
"count": 2
}
}
}

L’argomento aggregateBy consente di calcolare funzioni di aggregazione su dati raggruppati (o non raggruppati). Ogni aggregato richiede una function, un field opzionale e un alias obbligatorio.

input {TableName}AggregateInput {
function: AggregateFunction!
field: {TableName}AggregateField
alias: String!
}
FunzioneDescrizionefield richiesto?
COUNTContare le righeNo (usa COUNT(*) se omesso)
SUMSommare valori numerici
AVGCalcolare la media
MINTrovare il valore minimo
MAXTrovare il valore massimo
COUNT_DISTINCTContare valori distinti

L’enum field segue la stessa convenzione MAIUSCOLO di GroupBy.

L’alias è una stringa che scegli per nominare il risultato. Appare come chiave nell’oggetto di risposta aggregates.

Esempio: Contare e mediare l’età degli studenti raggruppati per stato attivo

Sezione intitolata “Esempio: Contare e mediare l’età degli studenti raggruppati per stato attivo”

Richiesta

query {
students(
groupBy: [ISACTIVE]
aggregateBy: [
{ function: COUNT, alias: "totalStudents" }
{ function: AVG, field: AGE, alias: "avgAge" }
]
) {
items {
isActive
}
count
aggregates
}
}

Risposta

{
"data": {
"students": {
"items": [
{ "isActive": true },
{ "isActive": false }
],
"count": 2,
"aggregates": [
{ "totalStudents": 5, "avgAge": 23.4 },
{ "totalStudents": 2, "avgAge": 21.0 }
]
}
}
}

Ogni voce nell’array aggregates corrisponde al gruppo allo stesso indice in items.

L’argomento having filtra i gruppi in base ai risultati aggregati, equivalente alla clausola SQL HAVING. Utilizza un tipo di input dedicato con tre campi.

input {TableName}HavingFilterInput {
alias: String!
operator: HavingOperator!
value: Float!
}
  • alias: Deve corrispondere a un alias definito in aggregateBy.
  • operator: L’operatore di confronto (vedi tabella sotto).
  • value: La soglia numerica da confrontare.
OperatoreEquivalente SQL
EQUALS=
NOT_EQUALS!=
GREATER_THAN>
GREATER_THAN_OR_EQUAL>=
LESS_THAN<
LESS_THAN_OR_EQUAL<=

Richiesta

query {
students(
groupBy: [CITYID]
aggregateBy: [
{ function: COUNT, alias: "studentCount" }
]
having: [
{ alias: "studentCount", operator: GREATER_THAN, value: 3 }
]
) {
items {
cityId
}
count
aggregates
}
}

Risposta

{
"data": {
"students": {
"items": [
{ "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" }
],
"count": 1,
"aggregates": [
{ "studentCount": 5 }
]
}
}
}

Solo i gruppi che soddisfano la condizione di aggregazione vengono restituiti.

L’argomento aggregateSort ordina i risultati raggruppati per un valore aggregato, anziché per un campo regolare.

input {TableName}AggregateSortInput {
alias: String!
direction: SortDirection!
}
  • alias: Deve corrispondere a un alias definito in aggregateBy.
  • direction: ASC (ascendente) o DESC (discendente).

Richiesta

query {
students(
groupBy: [CITYID]
aggregateBy: [
{ function: COUNT, alias: "studentCount" }
]
aggregateSort: [
{ alias: "studentCount", direction: DESC }
]
first: 3
) {
items {
cityId
}
count
aggregates
}
}

Risposta

{
"data": {
"students": {
"items": [
{ "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" },
{ "cityId": "0174dc55-d494-4ebc-a0e9-13575461cad4" },
{ "cityId": "a2b3c4d5-e6f7-8901-2345-678901234567" }
],
"count": 3,
"aggregates": [
{ "studentCount": 5 },
{ "studentCount": 3 },
{ "studentCount": 2 }
]
}
}
}

Puoi combinare filter, groupBy, aggregateBy, having, aggregateSort e first in una singola query per analisi complesse.

Esempio: Top 5 città di studenti attivi con età media superiore a 20, ordinate per età media

Sezione intitolata “Esempio: Top 5 città di studenti attivi con età media superiore a 20, ordinate per età media”

Richiesta

query {
students(
filter: { isActive: { equals: true } }
groupBy: [CITYID]
aggregateBy: [
{ function: COUNT, alias: "studentCount" }
{ function: AVG, field: AGE, alias: "avgAge" }
{ function: MAX, field: AGE, alias: "maxAge" }
]
having: [
{ alias: "avgAge", operator: GREATER_THAN, value: 20 }
]
aggregateSort: [
{ alias: "avgAge", direction: DESC }
]
first: 5
) {
items {
cityId
}
count
aggregates
}
}

Risposta

{
"data": {
"students": {
"items": [
{ "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" },
{ "cityId": "0174dc55-d494-4ebc-a0e9-13575461cad4" }
],
"count": 2,
"aggregates": [
{ "studentCount": 3, "avgAge": 24.3, "maxAge": 28 },
{ "studentCount": 2, "avgAge": 22.5, "maxAge": 25 }
]
}
}
}

Questa query:

  1. Filtra solo studenti attivi (filter).
  2. Raggruppa per città (groupBy).
  3. Calcola conteo, età media e età massima per ogni gruppo (aggregateBy).
  4. Mantiene solo gruppi con età media superiore a 20 (having).
  5. Ordina per età media decrescente (aggregateSort).
  6. Limita ai primi 5 gruppi (first).

Quando si utilizzano le aggregazioni, la risposta segue il tipo Connection standard con un campo aggiuntivo aggregates:

CampoTipoDescrizione
items[{TableName}!]!I record raggruppati (uno per gruppo, contenente i valori dei campi raggruppati)
countInt!Numero di gruppi restituiti
pageInfoPageInfo!Info paginazione (hasNextPage, hasPreviousPage)
aggregatesJSONArray di oggetti, ciascuno contenente i valori aggregati calcolati indicizzati per alias

L’array aggregates è parallelo a items — l’aggregato all’indice i corrisponde al gruppo all’indice i in items.

  • I valori enum GroupBy e AggregateField usano MAIUSCOLO del nome del campo in camelCase: payment_methodpaymentMethodPAYMENTMETHOD.
  • Gli alias having devono corrispondere a un alias definito in aggregateBy. Se non corrisponde, la condizione having viene ignorata.
  • Gli alias aggregateSort devono corrispondere a un alias definito in aggregateBy.
  • COUNT senza field usa COUNT(*), contando tutte le righe nel gruppo.
  • Più condizioni having possono essere combinate — tutte devono essere soddisfatte (logica AND).
  • Più voci aggregateSort sono applicate in ordine di priorità (la prima è l’ordinamento principale).
  • Gli argomenti di paginazione standard (first, skip, after, before) funzionano con i risultati raggruppati.
  • L’argomento filter viene applicato prima del raggruppamento (equivalente a SQL WHERE), mentre having viene applicato dopo il raggruppamento (equivalente a SQL HAVING).