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

## 什麼是指標（Metrics）

指標是 Cube Record 型別上可作為欄位選用的**聚合函式**，讓你在 GraphQL 查詢中直接計算統計量，無需後置處理。當與維度欄位一起選擇時，查詢會按所選維度分組，併為每組計算指標。

**支援的指標：**

| Metric  | 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" }
            }
          }
        }
      ]
    }
  }
}
```

***

## 組合多個指標

單個查詢中可選擇多個指標欄位：

```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 返回：成交筆數、總成交量、價格區間與獨立交易者數——一次查詢完成。

***

## 指標 vs 預聚合 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 Cube。
</Tip>

### 決策指引

<AccordionGroup>
  <Accordion title="需要 K 線圖">
    使用 **Pairs**（DWM）。已按分鐘預計算 open/high/low/close/volume，無需自己對 DEXTrades 做聚合。
  </Accordion>

  <Accordion title="需要按代幣統計買賣筆數">
    使用 **Tokens**（DWM）。已按分鐘預聚合成交筆數、成交量與獨立交易者數。
  </Accordion>

  <Accordion title="需要代幣持有者排名">
    使用 **TokenHolders**（DWS）。最新每位持有者餘額已預計算——比聚合 BalanceUpdates 快得多。
  </Accordion>

  <Accordion title="需要按 DEX 自定義拆分成交量">
    使用 **DEXTrades**，以 `count` + `sum(of: Trade_Buy_Amount)` 按 `Trade.Dex.ProtocolName` 分組。無現成 Cube 覆蓋時，DWD 指標是合適選擇。
  </Accordion>

  <Accordion title="需要按代幣檢視錢包 PnL">
    使用 **WalletTokenPnL**（DWS）。買入/賣出量與成交筆數已按錢包–代幣對預計算。
  </Accordion>
</AccordionGroup>

***

## 下一步

<CardGroup cols={2}>
  <Card title="資料 Cube" icon="cubes" href="/zh-Hant/graphql/schema/cubes">
    瀏覽全部 25 個 Cube 及其欄位結構。
  </Card>

  <Card title="查詢示例" icon="flask" href="/zh-Hant/graphql/examples/dex-trades">
    檢視包含指標與聚合的實戰查詢示例。
  </Card>
</CardGroup>
