[[ディメンションテーブル]] の中に置く日付属性 (登録日・生年月日など) は、プレーンな DATE 列をデフォルトにする。日付ディメンションへの外部キー (アウトリガー) にするのは、カレンダー属性で絞り込む要件があるときに限る例外である。
```mermaid
erDiagram
dim_user ||--o{ fct_order : "user_key"
dim_date ||--o{ fct_order : "order_date_key"
fct_order {
user_key int64 "[FK] ユーザーキー"
order_date_key int64 "[FK] 注文日キー"
order_amount int64 "[FA] 注文金額"
}
dim_user {
user_key int64 "[SK] ユーザーキー"
user_id string "[NK] ユーザーID"
registered_date date "登録日"
birth_date date "生年月日"
}
dim_date {
date_key int64 "[PK] 日付キー"
full_date date "日付 (yyyy-mm-dd)"
fiscal_year string "会計年"
holiday_name string "祝日名"
}
```
> [!info]
> 原典は『[[The Data Warehouse Toolkit]]』(3rd Edition) 3 章 "Retail Sales" の Outriggers 項。Kimball Group の [Outrigger Dimensions](https://www.kimballgroup.com/data-warehouse-business-intelligence-resources/kimball-techniques/dimensional-modeling-techniques/outrigger-dimension/) テクニックとしても解説されている。
## 例外: アウトリガーへの昇格
会計期間・祝日などのカレンダー属性で絞り込む要件が出たときに限り、元の DATE 列を残したまま日付ディメンションへの外部キーを追加する。参照先は列名を役名で変えた論理的なコピー、つまりロールプレイングされた日付ディメンションになる。
```mermaid
erDiagram
dim_user ||--o{ fct_order : "user_key"
dim_date ||--o{ fct_order : "order_date_key"
dim_date ||--o{ dim_user : "registered_date_key"
fct_order {
user_key int64 "[FK] ユーザーキー"
order_date_key int64 "[FK] 注文日キー"
order_amount int64 "[FA] 注文金額"
}
dim_user {
user_key int64 "[SK] ユーザーキー"
user_id string "[NK] ユーザーID"
registered_date date "登録日"
registered_date_key int64 "[FK] 登録日キー"
birth_date date "生年月日"
}
dim_date {
date_key int64 "[SK] 日付キー"
full_date date "日付 (yyyy-mm-dd)"
fiscal_year string "会計年"
holiday_name string "祝日名"
}
```
> [!note]
> 原典はこの構造を「許容されるが、規則ではなく例外であるべき (permissible, but they should be the exception rather than the rule)」と位置づけている。
この判断は、手に入る属性と結合コストのトレードオフで説明できる。年や月なら DATE 列から SQL の日付関数で導出できるため、アウトリガーは要らない。一方、会計期間や祝日は暦の規則から計算できず、日付ディメンションを結合しないと手に入らない。
導出できない属性が要件になった時点で初めて、結合が増えてスキーマがスノーフレーク化するコストを払う価値が生まれる。
## 関連ノート
- **[派生]** [[スタースキーマの NULL 可否は列の役割で決める]]: 日付属性が例外的に NULL を許容するという線引きの出どころ