> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chainstream.io/llms.txt
> Use this file to discover all available pages before exploring further.

# メトリクスと集計

> count、sum、avg、min、max、uniq でデータを集計 — of パラメータ、HAVING のための selectWhere、そして metrics と事前集計された Cubes の使い分け

## メトリクスとは

メトリクスは Cube の Record 型上のフィールドとして利用できる**集計関数**です。GraphQL クエリ内で直接統計を計算でき、後処理が不要になります。ディメンションフィールドとメトリクスフィールドを同時に選ぶと、選んだディメンションでグループ化し、各グループのメトリクスを計算します。

**サポートされるメトリクス:**

| メトリクス   | SQL に相当                        | 説明          |
| :------ | :----------------------------- | :---------- |
| `count` | `COUNT(*)` または `COUNT(column)` | 行数または異なる値の数 |
| `sum`   | `SUM(column)`                  | 数値の合計       |
| `avg`   | `AVG(column)`                  | 数値の平均       |
| `min`   | `MIN(column)`                  | 最小値         |
| `max`   | `MAX(column)`                  | 最大値         |
| `uniq`  | `COUNT(DISTINCT column)`       | ユニーク値の個数    |

***

## Record 型上のメトリクスフィールド

メトリクスは各 Cube の Record 型の**トップレベルフィールド**として現れます。すべての Cube がすべてのメトリクスをサポートするわけではなく、Cube 定義によります。

```graphql theme={null}
type DEXTradesRecord {
  # Dimension fields...
  Block { ... }
  Trade { ... }

  # Metric fields
  count: Int
  sum(of: DEXTradesSumOf!): Float
}
```

メトリクスを使うには、フィールド選択に含めるだけです:

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      tokenAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
      where: { Block: { Time: { after: "2025-03-27T00:00:00Z" } } }
    ) {
      count
      Trade { Dex { ProtocolName } }
    }
  }
}
```

このクエリは DEX 取引をプロトコル名でグループ化し、各グループの件数を返します。

***

## `of` パラメータ

`sum`、`avg`、`min`、`max`、`uniq` には、**どのディメンションを集計するか**を指定する `of` パラメータが必要です。`of` の値は Cube ごとに生成される列挙で、ディメンションパスの命名規則に従います。

```graphql theme={null}
sum(of: Trade_Buy_Amount)
avg(of: Trade_Buy_PriceInUSD)
min(of: Block_Time)
max(of: Trade_Sell_Amount)
uniq(of: Trade_Buy_Account_Owner)
```

### 例: DEX 別の買いボリューム合計

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      tokenAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
      where: { Block: { Time: { after: "2025-03-27T00:00:00Z" } } }
    ) {
      count
      sum(of: Trade_Buy_Amount)
      Trade { Dex { ProtocolName } }
    }
  }
}
```

**レスポンス:**

```json theme={null}
{
  "data": {
    "Solana": {
      "DEXTrades": [
        {
          "count": 1842,
          "sum": 2847291.45,
          "Trade": { "Dex": { "ProtocolName": "Raydium" } }
        },
        {
          "count": 923,
          "sum": 1293847.12,
          "Trade": { "Dex": { "ProtocolName": "Orca" } }
        }
      ]
    }
  }
}
```

***

## count — 行のカウント

`of` なしの `count` は、各グループの行の総数を数えます（`COUNT(*)` に相当）:

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      where: { Block: { Time: { after: "2025-03-27T00:00:00Z" } } }
    ) {
      count
    }
  }
}
```

ディメンションフィールドと併用すると、グループごとの件数を返します:

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      where: { Block: { Time: { after: "2025-03-27T00:00:00Z" } } }
    ) {
      count
      Trade { Dex { ProtocolName } }
    }
  }
}
```

***

## uniq — ユニーク数

`uniq` は SQL の `COUNT(DISTINCT column)` に対応します。ディメンションのユニーク値の個数を数えるときに使います:

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      tokenAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
      where: { Block: { Time: { after: "2025-03-27T00:00:00Z" } } }
    ) {
      uniq(of: Trade_Buy_Account_Owner)
    }
  }
}
```

これは、本日 Solana で USDC を取引した**ユニークな買い手ウォレット数**を返します。

***

## selectWhere — HAVING 相当のフィルター

`selectWhere` は、SQL の `HAVING` に似て、**集計結果に対する**フィルターをかけます。グループ化と集計の後に適用され、メトリクスの値に基づいてグループを絞り込めます。

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      where: { Block: { Time: { after: "2026-04-01T00:00:00Z" } } }
    ) {
      count(selectWhere: { gt: "100" })
      Trade { Dex { ProtocolName } }
    }
  }
}
```

これは取引が**100 件超**だった DEX プロトコルのみを返し、それ未満のプロトコルは結果から除きます。

<Note>
  `selectWhere` の値は**文字列**で渡す必要があります（例: `"100"` であり `100` ではない）。内部では数値として解釈されます。
</Note>

`selectWhere` で使える比較演算子:

| 演算子  | 説明    |
| :--- | :---- |
| `gt` | より大きい |
| `ge` | 以上    |
| `lt` | より小さい |
| `le` | 以下    |
| `eq` | 等しい   |

<Warning>
  **既知の制限:** `selectWhere` を使う場合、`orderBy` は暗黙の GROUP BY に含まれるディメンション（選択しているフィールド）または集計結果を参照する必要があります。GROUP BY に含まれないフィールド（例: `Block_Time`）で並べ替えるとデータベースエラーになります。
</Warning>

***

## 実践例: 上位トレーダー

本日のトークンについて、取引回数が多い上位 10 ウォレットを、買いボリューム合計とユニーク取引数とともに取得:

```graphql theme={null}
query TopTraders {
  Solana {
    DEXTrades(
      tokenAddress: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263"
      where: {
        Block: { Time: { after: "2025-03-27T00:00:00Z" } }
      }
      orderBy: {descending: Block_Time}
      limit: { count: 10 }
    ) {
      count
      sum(of: Trade_Buy_Amount)
      Trade {
        Buy {
          Account { Owner }
        }
      }
    }
  }
}
```

**レスポンス:**

```json theme={null}
{
  "data": {
    "Solana": {
      "DEXTrades": [
        {
          "count": 47,
          "sum": 892341023.5,
          "Trade": {
            "Buy": {
              "Account": { "Owner": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU" }
            }
          }
        },
        {
          "count": 31,
          "sum": 451203847.2,
          "Trade": {
            "Buy": {
              "Account": { "Owner": "3kMq5RezM9XBbBGRNxP9vXkJHAfG8S7gn5WfBsHFQr7T" }
            }
          }
        }
      ]
    }
  }
}
```

***

## 複数メトリクスの併用

1 つのクエリで複数のメトリクスフィールドを選べます:

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      tokenAddress: "So11111111111111111111111111111111111111112"
      where: {
        Block: { Time: { after: "2025-03-27T00:00:00Z" } }
      }
    ) {
      count
      sum(of: Trade_Buy_Amount)
      min(of: Trade_Buy_PriceInUSD)
      max(of: Trade_Buy_PriceInUSD)
      uniq(of: Trade_Buy_Account_Owner)
      Trade { Dex { ProtocolName } }
    }
  }
}
```

DEX ごとに、取引数、合計ボリューム、価格レンジ、ユニークトレーダー数を 1 クエリで取得できます。

***

## メトリクスと事前集計 Cube の使い分け

<Info>
  よくある質問: DWD Cube でメトリクスを使うべきか、DWM/DWS Cube を直接問い合わせるべきか？
</Info>

| アプローチ                                             | 使う場面                         | 性能                       |
| :------------------------------------------------ | :--------------------------- | :----------------------- |
| **DWD 上のメトリクス**（例: `DEXTrades.count`）             | カスタム集計、アドホックなグループ化、柔軟な時間窓    | 遅め — クエリ時に生イベントを集計       |
| **DWM Cube**（例: `Pairs`, `Tokens`）                | 標準的な時系列分析、OHLC チャート、時系列ボリューム | 速い — 事前計算された分単位ロールアップを読む |
| **DWS Cube**（例: `TokenHolders`, `WalletTokenPnL`） | 現在のスナップショット、累計、リーダーボード       | 最速 — 事前集計サマリーを読む         |

<Tip>
  **経験則**: ユースケースを DWM/DWS がカバーするならそちらを使う — 事前集計でかなり高速です。事前構築 Cube がサポートしないカスタムグループ化や集計ロジックが必要なときだけ、メトリクス付き DWD にフォールバックします。
</Tip>

### 判断ガイド

<AccordionGroup>
  <Accordion title="ローソク足チャートが必要">
    **Pairs**（DWM）を使います。分ごとの open/high/low/close/volume が既に計算済みです。DEXTrades を自前で集計する必要はありません。
  </Accordion>

  <Accordion title="トークンごとの買い／売り件数が必要">
    **Tokens**（DWM）を使います。分ごとの取引数、ボリューム、ユニークトレーダーが事前集計されています。
  </Accordion>

  <Accordion title="トークン保有者ランキングが必要">
    **TokenHolders**（DWS）を使います。保有者ごとの最新残高が事前計算されており、BalanceUpdates を集計するよりはるかに速いです。
  </Accordion>

  <Accordion title="DEX 別のカスタムボリューム内訳が必要">
    `Trade.Dex.ProtocolName` でグループ化した **DEXTrades** に `count` + `sum(of: Trade_Buy_Amount)` を使います。これ用の事前構築 Cube はないため、DWD メトリクスが適切です。
  </Accordion>

  <Accordion title="ウォレットのトークン別 PnL が必要">
    **WalletTokenPnL**（DWS）を使います。ウォレット–トークンペアごとの買い／売りボリュームと取引数が事前計算されています。
  </Accordion>
</AccordionGroup>

***

## 次のステップ

<CardGroup cols={2}>
  <Card title="Data Cubes" icon="cubes" href="/jp/graphql/schema/cubes">
    25 の Cube とフィールド構造を確認します。
  </Card>

  <Card title="クエリ例" icon="flask" href="/jp/graphql/examples/dex-trades">
    メトリクスと集計を使った実例クエリを見ます。
  </Card>
</CardGroup>
