グループ化と集計
Archie CoreはGraphQL APIを通じて強力なグループ化と集計機能を提供します。フィールド値でレコードをグループ化し、集計関数(COUNT、SUM、AVG、MIN、MAX、COUNT_DISTINCT)を計算し、HAVING条件でグループをフィルタリングし、集計値で結果をソートできます。
グループ化と集計を使用する場合、以下の引数が任意のリストクエリで利用可能です:
| 引数 | 型 | 説明 |
|---|---|---|
groupBy | [{TableName}GroupBy] | 結果をグループ化するフィールド |
aggregateBy | [{TableName}AggregateInput] | 計算する集計関数 |
having | [{TableName}HavingFilterInput] | 集計結果でグループをフィルタリング |
aggregateSort | [{TableName}AggregateSortInput] | 集計値で結果をソート |
これらの引数はfilter、first、skip、orderByなどの標準引数と組み合わせることができます。
GroupBy
Section titled “GroupBy”groupBy引数は、グループ化するフィールドを表すenum値の配列を受け取ります。enum値は、camelCaseのフィールド名を大文字に変換したパターンに従います。
命名規則:
| 列名(DB) | フィールド名(GraphQL) | GroupBy enum値 |
|---|---|---|
payment_method | paymentMethod | PAYMENTMETHOD |
created_at | createdAt | CREATEDAT |
status | status | STATUS |
category_id | categoryId | CATEGORYID |
例:アクティブ状態で学生をグループ化
Section titled “例:アクティブ状態で学生をグループ化”リクエスト
query { students(groupBy: [ISACTIVE]) { items { isActive } count }}レスポンス
{ "data": { "students": { "items": [ { "isActive": true }, { "isActive": false } ], "count": 2 } }}AggregateBy
Section titled “AggregateBy”aggregateBy引数は、グループ化された(またはグループ化されていない)データに対して集計関数を計算できます。各集計にはfunction、オプションのfield、必須のaliasが必要です。
AggregateInput構造
Section titled “AggregateInput構造”input {TableName}AggregateInput { function: AggregateFunction! field: {TableName}AggregateField alias: String!}利用可能な集計関数
Section titled “利用可能な集計関数”| 関数 | 説明 | field必須? |
|---|---|---|
COUNT | 行数をカウント | いいえ(省略時はCOUNT(*)を使用) |
SUM | 数値を合計 | はい |
AVG | 平均を計算 | はい |
MIN | 最小値を検索 | はい |
MAX | 最大値を検索 | はい |
COUNT_DISTINCT | 一意の値をカウント | はい |
fieldのenumはGroupByと同じ大文字の規則に従います。
aliasは結果に名前を付けるために選択する文字列です。aggregatesレスポンスオブジェクトのキーとして表示されます。
例:アクティブ状態でグループ化された学生の数と平均年齢
Section titled “例:アクティブ状態でグループ化された学生の数と平均年齢”リクエスト
query { students( groupBy: [ISACTIVE] aggregateBy: [ { function: COUNT, alias: "totalStudents" } { function: AVG, field: AGE, alias: "avgAge" } ] ) { items { isActive } count aggregates }}レスポンス
{ "data": { "students": { "items": [ { "isActive": true }, { "isActive": false } ], "count": 2, "aggregates": [ { "totalStudents": 5, "avgAge": 23.4 }, { "totalStudents": 2, "avgAge": 21.0 } ] } }}aggregates配列の各エントリは、itemsの同じインデックスにあるグループに対応します。
Having
Section titled “Having”having引数は、集計結果に基づいてグループをフィルタリングします。SQLのHAVING句に相当します。3つのフィールドを持つ専用の入力型を使用します。
HavingFilterInput構造
Section titled “HavingFilterInput構造”input {TableName}HavingFilterInput { alias: String! operator: HavingOperator! value: Float!}alias:aggregateByで定義されたaliasと一致する必要があります。operator:比較演算子(下の表を参照)。value:比較する数値のしきい値。
利用可能な演算子
Section titled “利用可能な演算子”| 演算子 | SQL相当 |
|---|---|
EQUALS | = |
NOT_EQUALS | != |
GREATER_THAN | > |
GREATER_THAN_OR_EQUAL | >= |
LESS_THAN | < |
LESS_THAN_OR_EQUAL | <= |
例:学生が3人以上の都市
Section titled “例:学生が3人以上の都市”リクエスト
query { students( groupBy: [CITYID] aggregateBy: [ { function: COUNT, alias: "studentCount" } ] having: [ { alias: "studentCount", operator: GREATER_THAN, value: 3 } ] ) { items { cityId } count aggregates }}レスポンス
{ "data": { "students": { "items": [ { "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" } ], "count": 1, "aggregates": [ { "studentCount": 5 } ] } }}集計条件を満たすグループのみが返されます。
AggregateSort
Section titled “AggregateSort”aggregateSort引数は、通常のフィールドではなく集計値でグループ化された結果をソートします。
AggregateSortInput構造
Section titled “AggregateSortInput構造”input {TableName}AggregateSortInput { alias: String! direction: SortDirection!}alias:aggregateByで定義されたaliasと一致する必要があります。direction:ASC(昇順)またはDESC(降順)。
例:学生数で上位3都市
Section titled “例:学生数で上位3都市”リクエスト
query { students( groupBy: [CITYID] aggregateBy: [ { function: COUNT, alias: "studentCount" } ] aggregateSort: [ { alias: "studentCount", direction: DESC } ] first: 3 ) { items { cityId } count aggregates }}レスポンス
{ "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 } ] } }}すべての機能を組み合わせる
Section titled “すべての機能を組み合わせる”複雑な分析のために、1つのクエリでfilter、groupBy、aggregateBy、having、aggregateSort、firstを組み合わせることができます。
例:平均年齢が20を超えるアクティブな学生の上位5都市、平均年齢でソート
Section titled “例:平均年齢が20を超えるアクティブな学生の上位5都市、平均年齢でソート”リクエスト
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 }}レスポンス
{ "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 } ] } }}このクエリは:
- フィルタリング アクティブな学生のみ(
filter)。 - グループ化 都市別(
groupBy)。 - 計算 各グループの数、平均年齢、最大年齢(
aggregateBy)。 - 保持 平均年齢が20を超えるグループのみ(
having)。 - ソート 平均年齢の降順(
aggregateSort)。 - 制限 上位5グループ(
first)。
レスポンス構造
Section titled “レスポンス構造”集計を使用する場合、レスポンスは追加のaggregatesフィールドを持つ標準のConnection型に従います:
| フィールド | 型 | 説明 |
|---|---|---|
items | [{TableName}!]! | グループ化されたレコード(グループごとに1つ、グループ化されたフィールド値を含む) |
count | Int! | 返されたグループ数 |
pageInfo | PageInfo! | ページネーション情報(hasNextPage、hasPreviousPage) |
aggregates | JSON | 各オブジェクトがaliasでインデックス付けされた計算された集計値を含むオブジェクトの配列 |
aggregates配列はitemsと並行しています — インデックスiの集計はitemsのインデックスiのグループに対応します。
重要な注意事項
Section titled “重要な注意事項”- GroupByとAggregateFieldのenum値はcamelCaseフィールド名の大文字を使用します:
payment_method→paymentMethod→PAYMENTMETHOD。 - havingのaliasは
aggregateByで定義されたaliasと一致する必要があります。一致しない場合、having条件は無視されます。 - aggregateSortのaliasは
aggregateByで定義されたaliasと一致する必要があります。 - fieldなしのCOUNTは
COUNT(*)を使用し、グループ内のすべての行をカウントします。 - 複数のhaving条件を組み合わせることができます — すべて満たす必要があります(AND論理)。
- 複数のaggregateSortエントリは優先順位の順に適用されます(最初のエントリが主ソート)。
- 標準のページネーション引数(
first、skip、after、before)はグループ化された結果で動作します。 - filter引数はグループ化の前に適用されます(SQL WHEREに相当)、havingはグループ化の後に適用されます(SQL HAVINGに相当)。