Zum Inhalt springen

Gruppierung und Aggregationen

Archie Core bietet leistungsstarke Gruppierungs- und Aggregationsfunktionen über seine GraphQL-API. Sie können Datensätze nach Feldwerten gruppieren, Aggregationsfunktionen (COUNT, SUM, AVG, MIN, MAX, COUNT_DISTINCT) berechnen, Gruppen mit HAVING-Bedingungen filtern und Ergebnisse nach aggregierten Werten sortieren.

Bei Verwendung von Gruppierung und Aggregationen stehen die folgenden Argumente für jede Listenabfrage zur Verfügung:

ArgumentTypBeschreibung
groupBy[{TableName}GroupBy]Felder zum Gruppieren der Ergebnisse
aggregateBy[{TableName}AggregateInput]Zu berechnende Aggregationsfunktionen
having[{TableName}HavingFilterInput]Gruppen nach aggregierten Ergebnissen filtern
aggregateSort[{TableName}AggregateSortInput]Ergebnisse nach aggregierten Werten sortieren

Diese Argumente können mit Standardargumenten wie filter, first, skip und orderBy kombiniert werden.

Das Argument groupBy akzeptiert ein Array von Enum-Werten, die die zu gruppierenden Felder darstellen. Enum-Werte folgen dem Muster: der camelCase-Feldname in GROSSBUCHSTABEN umgewandelt.

Namenskonvention:

Spaltenname (DB)Feldname (GraphQL)GroupBy-Enum-Wert
payment_methodpaymentMethodPAYMENTMETHOD
created_atcreatedAtCREATEDAT
statusstatusSTATUS
category_idcategoryIdCATEGORYID

Beispiel: Studenten nach aktivem Status gruppieren

Abschnitt betitelt „Beispiel: Studenten nach aktivem Status gruppieren“

Anfrage

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

Antwort

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

Das Argument aggregateBy ermöglicht die Berechnung von Aggregationsfunktionen über gruppierte (oder nicht gruppierte) Daten. Jede Aggregation erfordert eine function, ein optionales field und einen obligatorischen alias.

input {TableName}AggregateInput {
function: AggregateFunction!
field: {TableName}AggregateField
alias: String!
}
FunktionBeschreibungfield erforderlich?
COUNTZeilen zählenNein (verwendet COUNT(*) wenn weggelassen)
SUMNumerische Werte summierenJa
AVGDurchschnitt berechnenJa
MINMinimalwert findenJa
MAXMaximalwert findenJa
COUNT_DISTINCTUnterschiedliche Werte zählenJa

Das field-Enum folgt derselben GROSSBUCHSTABEN-Konvention wie GroupBy.

Der alias ist eine Zeichenkette, die Sie zur Benennung des Ergebnisses wählen. Er erscheint als Schlüssel im aggregates-Antwortobjekt.

Beispiel: Anzahl und Durchschnittsalter von Studenten gruppiert nach aktivem Status

Abschnitt betitelt „Beispiel: Anzahl und Durchschnittsalter von Studenten gruppiert nach aktivem Status“

Anfrage

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

Antwort

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

Jeder Eintrag im aggregates-Array entspricht der Gruppe am gleichen Index in items.

Das Argument having filtert Gruppen basierend auf aggregierten Ergebnissen, entspricht der SQL-Klausel HAVING. Es verwendet einen dedizierten Eingabetyp mit drei Feldern.

input {TableName}HavingFilterInput {
alias: String!
operator: HavingOperator!
value: Float!
}
  • alias: Muss mit einem in aggregateBy definierten Alias übereinstimmen.
  • operator: Der Vergleichsoperator (siehe Tabelle unten).
  • value: Der numerische Schwellenwert zum Vergleichen.
OperatorSQL-Äquivalent
EQUALS=
NOT_EQUALS!=
GREATER_THAN>
GREATER_THAN_OR_EQUAL>=
LESS_THAN<
LESS_THAN_OR_EQUAL<=

Anfrage

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

Antwort

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

Nur Gruppen, die die Aggregationsbedingung erfüllen, werden zurückgegeben.

Das Argument aggregateSort sortiert die gruppierten Ergebnisse nach einem aggregierten Wert anstatt nach einem regulären Feld.

input {TableName}AggregateSortInput {
alias: String!
direction: SortDirection!
}
  • alias: Muss mit einem in aggregateBy definierten Alias übereinstimmen.
  • direction: ASC (aufsteigend) oder DESC (absteigend).

Anfrage

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

Antwort

{
"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 }
]
}
}
}

Sie können filter, groupBy, aggregateBy, having, aggregateSort und first in einer einzigen Abfrage für komplexe Analysen kombinieren.

Beispiel: Top 5 Städte aktiver Studenten mit Durchschnittsalter über 20, sortiert nach Durchschnittsalter

Abschnitt betitelt „Beispiel: Top 5 Städte aktiver Studenten mit Durchschnittsalter über 20, sortiert nach Durchschnittsalter“

Anfrage

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
}
}

Antwort

{
"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 }
]
}
}
}

Diese Abfrage:

  1. Filtert nur aktive Studenten (filter).
  2. Gruppiert nach Stadt (groupBy).
  3. Berechnet Anzahl, Durchschnittsalter und Maximalalter für jede Gruppe (aggregateBy).
  4. Behält nur Gruppen mit Durchschnittsalter über 20 (having).
  5. Sortiert nach Durchschnittsalter absteigend (aggregateSort).
  6. Begrenzt auf die Top 5 Gruppen (first).

Bei Verwendung von Aggregationen folgt die Antwort dem Standard-Connection-Typ mit einem zusätzlichen Feld aggregates:

FeldTypBeschreibung
items[{TableName}!]!Die gruppierten Datensätze (einer pro Gruppe, mit den gruppierten Feldwerten)
countInt!Anzahl der zurückgegebenen Gruppen
pageInfoPageInfo!Paginierungsinfo (hasNextPage, hasPreviousPage)
aggregatesJSONArray von Objekten, jeweils mit den berechneten Aggregatwerten nach Alias indexiert

Das aggregates-Array ist parallel zu items — das Aggregat am Index i entspricht der Gruppe am Index i in items.

  • GroupBy- und AggregateField-Enum-Werte verwenden GROSSBUCHSTABEN des camelCase-Feldnamens: payment_methodpaymentMethodPAYMENTMETHOD.
  • Having-Aliase müssen übereinstimmen mit einem in aggregateBy definierten Alias. Bei Nichtübereinstimmung wird die Having-Bedingung ignoriert.
  • AggregateSort-Aliase müssen übereinstimmen mit einem in aggregateBy definierten Alias.
  • COUNT ohne field verwendet COUNT(*), zählt alle Zeilen in der Gruppe.
  • Mehrere Having-Bedingungen können kombiniert werden — alle müssen erfüllt sein (AND-Logik).
  • Mehrere aggregateSort-Einträge werden nach Priorität angewendet (erster Eintrag ist die Hauptsortierung).
  • Standard-Paginierungsargumente (first, skip, after, before) funktionieren mit gruppierten Ergebnissen.
  • Das filter-Argument wird vor der Gruppierung angewendet (äquivalent zu SQL WHERE), während having nach der Gruppierung angewendet wird (äquivalent zu SQL HAVING).