The Data Warehouse Toolkit を読む #2: Retail Sales

 
前回からの続きをメモ。

前回の記事:
The Data Warehouse Toolkit を読む #1: 基本の4ステップ

 

小売業におけるファクトテーブル

小売業におけるファクトテーブルの例はこんな感じになる。

小売業のファクトテーブル例

POS トランザクションにおける個別の商品毎に1行という粒度になっている。
平たく言うと SKU ごとに1行って事か。
ディメンションテーブルを持つカラムは FK ラベルがついてる。

ところで DD ってなんだと思ったら Degenerate Dimension の事で、ディメンションテーブルを持たないディメンションの事だそうで。
この例だとトランザクションIDが該当してる。

SKU 毎に一行じゃなくてトランザクション毎に1行にしちゃうと、 Transaction Dimension が必要になるな。
そしてその結果 Transaction Dimension から更に Product Dimension が派生してスノーフレーク型スキーマになってメンドクサイと見た。

 

小売業におけるディメンション

各ディメンションテーブルについてメモ

 

Date Dimension

どんな業種であれ必ずあるだろう日付ディメンション。
例えばこんなカラムで構成される。

日付ディメンションテーブルの例

日付ディメンションは他のディメンションと違ってあらかじめ用意する事が出来るので先に作っておいてOK。
時間ごとや秒ごとにする必要はない。それだと細かすぎるというかデータ増えすぎる。

日毎なら20年でも約7,300行で収まる。
トランザクションが発生した時間や秒も記録したいならファクトテーブルに入れればよい。

 

Product Dimension

商品ディメンションは SKU 毎の情報を格納する。
ググったら日本のコンビニだとお店に存在する SKU は約 2,500 個。
スーパーマーケットだと規模によって 約 15,000 〜 60,000 個らしい。
商品ディメンションの例はこんな感じ。

商品ディメンションの例

なお SKU はプライマリキーではない。
NK つまりナチュラルキーなんだけど、そもそもディメンショナルモデルにおいてナチュラルキーは絶対にプライマリキーとして使わない。
必ず代理のサロゲートキーを使う。
というわけで SKU はプライマリキーじゃない。
ナチュラルキーはビジネス上の理由で、例えば合併とか事業再編で変わったり再利用される可能性があるから、という理由。

なお実際に Product Dimension テーブルを作ろうとすると属性情報があれやこれやあってカラム数も結局50個くらいあったりする。

 

Store Dimension

チェーン店の店舗別の情報が格納される店舗ディメンション。
例えばこんなカラム構成。

店舗ディメンションの例

ここでも当然ナチュラルキーの店舗番号はプライマリキーではない。

さて、この店舗ディメンションには店舗オープン日などの日付カラムが存在している。
この日付に対しては先に作った日付ディメンションから CREATE VIEW して「店舗オープン日ディメンションビュー」を作成するのが良い。

こういう補助テーブルを Outrigger (アウトリガー:舷外浮剤) とも言う。
ただしディメンションテーブルから更に補助テーブルを伸ばすスノーフレーク型のスキーマは管理が煩雑になるから推奨されない。
日付以外には多様禁止。

 

Promotion Dimension

プロモーション情報を格納する Promotion Dimension は他のディメンションと性格が異なる。
プロモーションディメンションは Causal Dimension (原因ディメンション) と言われていて、売上に影響を及ぼした可能性があるディメンションである。

プロモーションディメンションの例

Ad, Display, Coupon という別々のカラムに分かれてるんだけど、これは併用可能なケースを考慮してるそうなんだが、ここまで分けなくてもOKらしい。
データ利用者が BI で分析する時に別々のカラムになってる方が分かりやすそうとかそんな理由。

で、ファクトテーブルには null カラムを作っては行けないという原則がある。
プロモーションに関係ない商品が売れた場合、ファクトテーブルにはせめて 0 とか -1 などのプロモーション適用外である事が分かる値を入れる。
それでもって Promotion Demension と LEFT JOIN すれば OK.

 

その他のディメンション

以上のような感じで Cashier Dimension や Payment Method Dimension を設計すればOK.

しかし、支払い方法を複数使える場合はどうすべきなんだろう。
Payment Dimension テーブル側を Array にしちゃうとか。

さらに、 ディメンションテーブルを持たない Degenerate Dimension てのもある。
今回のファクトテーブル例だと POSトランザクションIDがそう。
このファクトだとトランザクションIDはSKU毎に分解されてるので、トランザクションIDはあくまでも親カテゴリみたいな扱いになる。

なお、Transaction Dimension てのを作ってそっちと JOIN するってのもアリらしい。
そうすれば Transaction に紐づく請求情報などと繋げられる。
まぁ要件次第だ。

 

Factless Fact Table

小売業のファクトテーブルには「売れた商品」の情報が入るわけだが、「売れなかった商品」の情報は当然入らない。
例えばセール対象品なのに一切売れなかった商品は何か?という分析が出来ない。

というわけで、KPI指標と紐付かないリストテーブルを別途用意して比較するという手法がある。
例えば「プロモーション対象商品ファクト」なんていうテーブルを作る。

プロモ対象商品ファクトテーブルの例

これを日別にデータを投入して、分析の際に JOIN して比較するという事。

 

とにかくサロゲートキーを使う

本読んでるととにかく「ナチュラルキーは使うな、サロゲートキー使え」というメッセージが強調されてる。
たしかにナチュラルキーは恒久的じゃないもんが多いからダメ絶対。

そしてここまでメモ書いて気づいたがディメンションの更新については考慮されてない構成だ。
Slowly-Changing-Dimension を Type2 型(追記型)にするなら有効期間(開始&終了)と現在値を判定するためのカラムも必要。

だがしかし今回はここまで。

つづく。

次の記事:
The Data Warehouse Toolkit を読む #3: Inventory