Przejdź do głównej zawartości

Grupowanie i Agregacje

Archie Core oferuje potężne możliwości grupowania i agregacji poprzez interfejs API GraphQL. Możesz grupować rekordy według wartości pól, obliczać funkcje agregujące (COUNT, SUM, AVG, MIN, MAX, COUNT_DISTINCT), filtrować grupy za pomocą warunków HAVING i sortować wyniki według wartości zagregowanych.

Przy użyciu grupowania i agregacji następujące argumenty są dostępne w dowolnym zapytaniu listy:

ArgumentTypOpis
groupBy[{TableName}GroupBy]Pola, według których grupować wyniki
aggregateBy[{TableName}AggregateInput]Funkcje agregujące do obliczenia
having[{TableName}HavingFilterInput]Filtrowanie grup według wyników agregacji
aggregateSort[{TableName}AggregateSortInput]Sortowanie wyników według wartości zagregowanych

Te argumenty można łączyć ze standardowymi argumentami takimi jak filter, first, skip i orderBy.

Argument groupBy przyjmuje tablicę wartości enum reprezentujących pola, według których grupować. Wartości enum stosują wzorzec: nazwa pola w camelCase przekonwertowana na WIELKIE_LITERY.

Konwencja nazewnictwa:

Nazwa kolumny (DB)Nazwa pola (GraphQL)Wartość enum GroupBy
payment_methodpaymentMethodPAYMENTMETHOD
created_atcreatedAtCREATEDAT
statusstatusSTATUS
category_idcategoryIdCATEGORYID

Przykład: Grupowanie studentów według statusu aktywnego

Dział zatytułowany „Przykład: Grupowanie studentów według statusu aktywnego”

Żądanie

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

Odpowiedź

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

Argument aggregateBy umożliwia obliczanie funkcji agregujących na danych zgrupowanych (lub niezgrupowanych). Każda agregacja wymaga function, opcjonalnego field i obowiązkowego alias.

input {TableName}AggregateInput {
function: AggregateFunction!
field: {TableName}AggregateField
alias: String!
}
FunkcjaOpisCzy field wymagane?
COUNTLiczenie wierszyNie (używa COUNT(*) gdy pominięte)
SUMSumowanie wartości numerycznychTak
AVGObliczanie średniejTak
MINZnajdowanie wartości minimalnejTak
MAXZnajdowanie wartości maksymalnejTak
COUNT_DISTINCTLiczenie unikalnych wartościTak

Enum field stosuje tę samą konwencję WIELKICH_LITER co GroupBy.

alias to ciąg znaków, który wybierasz do nazwania wyniku. Pojawia się jako klucz w obiekcie odpowiedzi aggregates.

Przykład: Liczenie i uśrednianie wieku studentów zgrupowanych według statusu aktywnego

Dział zatytułowany „Przykład: Liczenie i uśrednianie wieku studentów zgrupowanych według statusu aktywnego”

Żądanie

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

Odpowiedź

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

Każdy wpis w tablicy aggregates odpowiada grupie o tym samym indeksie w items.

Argument having filtruje grupy według wyników agregacji, odpowiednik klauzuli SQL HAVING. Używa dedykowanego typu wejściowego z trzema polami.

input {TableName}HavingFilterInput {
alias: String!
operator: HavingOperator!
value: Float!
}
  • alias: Musi pasować do aliasu zdefiniowanego w aggregateBy.
  • operator: Operator porównania (patrz tabela poniżej).
  • value: Próg numeryczny, z którym porównywać.
OperatorOdpowiednik SQL
EQUALS=
NOT_EQUALS!=
GREATER_THAN>
GREATER_THAN_OR_EQUAL>=
LESS_THAN<
LESS_THAN_OR_EQUAL<=

Żądanie

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

Odpowiedź

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

Zwracane są tylko grupy spełniające warunek agregacji.

Argument aggregateSort sortuje zgrupowane wyniki według wartości zagregowanej, zamiast według zwykłego pola.

input {TableName}AggregateSortInput {
alias: String!
direction: SortDirection!
}
  • alias: Musi pasować do aliasu zdefiniowanego w aggregateBy.
  • direction: ASC (rosnąco) lub DESC (malejąco).

Żądanie

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

Odpowiedź

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

Możesz łączyć filter, groupBy, aggregateBy, having, aggregateSort i first w jednym zapytaniu do złożonych analiz.

Przykład: Top 5 miast aktywnych studentów ze średnim wiekiem powyżej 20, posortowane według średniego wieku

Dział zatytułowany „Przykład: Top 5 miast aktywnych studentów ze średnim wiekiem powyżej 20, posortowane według średniego wieku”

Żądanie

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

Odpowiedź

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

To zapytanie:

  1. Filtruje tylko aktywnych studentów (filter).
  2. Grupuje według miasta (groupBy).
  3. Oblicza liczbę, średni wiek i maksymalny wiek w każdej grupie (aggregateBy).
  4. Zachowuje tylko grupy ze średnim wiekiem powyżej 20 (having).
  5. Sortuje według średniego wieku malejąco (aggregateSort).
  6. Ogranicza do 5 najlepszych grup (first).

Przy użyciu agregacji odpowiedź stosuje standardowy typ Connection z dodatkowym polem aggregates:

PoleTypOpis
items[{TableName}!]!Zgrupowane rekordy (jeden na grupę, z wartościami pól zgrupowanych)
countInt!Liczba zwróconych grup
pageInfoPageInfo!Informacje o stronicowaniu (hasNextPage, hasPreviousPage)
aggregatesJSONTablica obiektów, każdy z obliczonymi wartościami zagregowanymi indeksowanymi według aliasu

Tablica aggregates jest równoległa do items — agregat o indeksie i odpowiada grupie o indeksie i w items.

  • Wartości enum GroupBy i AggregateField używają WIELKICH_LITER nazwy pola w camelCase: payment_methodpaymentMethodPAYMENTMETHOD.
  • Aliasy having muszą pasować do aliasu zdefiniowanego w aggregateBy. Jeśli nie pasują, warunek having jest ignorowany.
  • Aliasy aggregateSort muszą pasować do aliasu zdefiniowanego w aggregateBy.
  • COUNT bez field używa COUNT(*), licząc wszystkie wiersze w grupie.
  • Wiele warunków having można łączyć — wszystkie muszą być spełnione (logika AND).
  • Wiele wpisów aggregateSort stosuje się w kolejności priorytetu (pierwszy to sortowanie główne).
  • Standardowe argumenty stronicowania (first, skip, after, before) działają ze zgrupowanymi wynikami.
  • Argument filter stosuje się przed grupowaniem (odpowiednik SQL WHERE), podczas gdy having stosuje się po grupowaniu (odpowiednik SQL HAVING).