ファクトテーブルは、ビジネスプロセスの測定結果を格納するテーブルである。[[ディメンショナルモデリング]] のスタースキーマの中心に位置し、周囲のディメンションテーブルと結合することで、誰が、いつ、どこで、といった文脈付きで数値 (ファクト) を分析できる。
データウェアハウスの数値データはほぼすべてファクトテーブルに集まるため、列数は少ないまま行数が膨大になる。その結果、容量とクエリ処理量の大半をこのテーブルが占める。
> [!info]
> 原典は『[[The Data Warehouse Toolkit]]』(3rd Edition) 1 章の "Fact Tables for Measurements" 項。Kimball Group の [Fact Table Structure](https://www.kimballgroup.com/data-warehouse-business-intelligence-resources/kimball-techniques/dimensional-modeling-techniques/fact-table-structure/) テクニックとしても解説されている。
## 分類
ファクトテーブルは、ビジネスプロセスをどの単位で記録するかに応じて、次の 3 つの型に分類される。
| 型 | BEAM ✲ 記法 | 説明 |
| ------------------ | --------- | ------------------------------------------------------ |
| トランザクションファクトテーブル | `TF` | 測定したビジネスイベント 1 件を 1 行として記録する (例: 注文明細) |
| 周期スナップショットファクトテーブル | `PS` | 日次や月次など決まった間隔で、対象ごとの状態を 1 行として記録する (例: 商品ごとの月末在庫) |
| 累積スナップショットファクトテーブル | `AS` | 始点と終点が明確なビジネスプロセス 1 件を 1 行として記録する (例: 注文から配達までの履行プロセス) |
3 つの型は、どれか 1 つを選ぶ排他的な関係ではない。同じ注文プロセスでも、売上の分析にはトランザクション、受注残の推移には周期スナップショット、注文から配達までのリードタイムには累積スナップショットが向いており、答えたい問いに応じて複数の型を併用する ([Design Tip #167](https://www.kimballgroup.com/2014/06/design-tip-167-complementary-fact-table-types/))。
> [!note]
> ファクトを 1 つも持たないファクトテーブルはファクトレスファクトテーブルと呼ばれる。これは 4 つ目の型ではなく、ファクトレスファクトテーブルも 3 つの型のいずれかに属する。
>
> 起きた事実だけを記録するものはトランザクションとして、状態や関係の成立を記録するものは周期スナップショットとして現れる。
## 構造
ファクトテーブルの列は、次の 4 種類で構成される。この枠組みは 3 つの型すべてに共通している。
| 要素 | BEAM ✲ 記法 | 説明 |
| ------------------------ | ---------------- | ---------------------- |
| サロゲートキー | `SK` | 行を一意に識別するために生成するキー |
| 外部キー | `FK` | ディメンションテーブルと結合するキー |
| [[Degenerate Dimension]] | `DD` | ファクトテーブルに直接置かれるディメンション |
| ファクト (メジャー) | `FA`, `SA`, `NA` | 分析対象となる数値 (事実) |
注文明細を粒度とするトランザクションファクトテーブル `fct_order` で 4 種類を示す。
```mermaid
erDiagram
dim_date ||--|{ fct_order : "date_key"
dim_customer ||--|{ fct_order : "customer_key"
dim_product ||--|{ fct_order : "product_key"
fct_order["fct_order [TF]"] {
order_key int64 "[SK]"
date_key int64 "[FK]"
customer_key int64 "[FK]"
product_key int64 "[FK]"
order_id string "[DD]"
order_line_number int64 "[DD]"
order_date datetime "[DD]"
quantity int64 "[FA]"
amount int64 "[FA]"
}
```