はじめに
BIツールのキューブ、ディメンション、メジャーという言葉の意味を押さえると、今度は「自分のデータでは、何をディメンションにして、何をメジャーにすればよいのか」という設計の話が一緒についてきます。 この切り口の決め方には、データウェアハウスの分野で確立された考え方があります。 この記事では、カフェチェーンの売上データを例に、手元の元データと「集計したいこと」から、キューブの形を決めるまでの手順を順に整理します。
前回の記事「BIツールの「キューブ」とは?リレーショナルデータベースとの関係からざっくり理解する」の続きです。 キューブ、ディメンション、メジャーという言葉自体の説明は、前回の記事にありますので、こちらも合わせてご覧ください。
題材と元データ
手順の説明に入る前に、この記事で使う題材を置きます。 例えば、3店舗を運営するカフェチェーンを考えます。
レジ(POSシステム)には、会計のたびに次のような明細が記録されていきます。
| 伝票番号 | 日時 | 店舗 | 商品 | 単価 | 数量 | 金額 |
|---|---|---|---|---|---|---|
| 1001 | 2026-07-01 08:12 | 駅前店 | カフェラテ | 480 | 1 | 480 |
| 1001 | 2026-07-01 08:12 | 駅前店 | クロワッサン | 300 | 2 | 600 |
| 1002 | 2026-07-01 08:15 | 本店 | ブレンドコーヒー | 400 | 1 | 400 |
1行が「1枚のレシートの中の1商品」で、1枚のレシートに複数の商品があれば、その数だけ行ができます。
元データについて、先に押さえておきたいことがあります。 分析用のデータは、分析のために新しく集めるものではなく、このような業務の記録をそのまま持ってくるのが基本です。 レジの明細、ECサイトの注文履歴、予約システムの予約記録。 業務システムが日々の仕事の中で書き溜めているデータが、キューブの材料になります。
この明細と、「何を集計したいか」という要望の2つを材料に、設計を進めます。
手順の全体像
この記事では、次の5ステップで進めます。
- 集計したいことの書き出し
- ディメンションとメジャーの取り出し
- 粒度(1行が表すもの)の決定
- ファクトテーブルとディメンションテーブルへの分割
- BIツールでの集計
ステップ1:集計したいことの書き出し
設計は、技術の言葉ではなく業務の言葉から始めます。 このカフェチェーンの店長会議で出てきそうな要望を、そのまま文にします。
「月ごとに、店舗ごとに、売上金額の合計を見たい」
この段階では、テーブルもSQLも考えません。 「誰が、どんな切り口で、どんな数値を見たいのか」が文になっていれば、材料としては十分です。
ステップ2:ディメンションとメジャーの取り出し
書き出した文を、部品に分解します。
「〜ごとに」「〜別に」に当たる言葉がディメンションの候補、「見たい数値」に当たる言葉がメジャーの候補です。
先ほどの文なら、次のように分かれます。
| 文の部品 | 役割 | 設計上の扱い |
|---|---|---|
| 月ごとに | 切り口 | ディメンション(日付) |
| 店舗ごとに | 切り口 | ディメンション(店舗) |
| 売上金額の合計 | 集計する数値 | メジャー(金額) |
「月ごとに」は、そのまま「月」をディメンションにするのではなく、「日付」というディメンションの中の1つの粒度として扱います。 日付は年、四半期、月、日と階層で持てるので、月別で見た後に「では7月のどの日か」と掘り下げる操作(ドリルダウン)につながります。
要望が複数あれば、同じ分解を繰り返します。 出てきた切り口と数値の和集合が、キューブに必要なディメンションとメジャーの一覧になります。
ステップ3:粒度(1行が表すもの)の決定
切り口と数値が出たら、次に「集計の元になる表の1行が、何を表すか」を決めます。 この決めごとは粒度(グレイン)と呼ばれます。
今回の元データなら、粒度の選び方は複数あります。
- 案A — 1行=レシートの中の1商品(元データの明細そのまま)
- 案B — 1行=日×店舗×商品の合計(明細を1日分まとめる)
- 案C — 1行=月×店舗の合計(月次レポートの形)
下に行くほど行数は減って扱いやすく見えます。 ただし、粗くまとめた時点で、答えられない質問が生まれます。 案Cで保存すると「曜日別ではどうか」「商品別ではどうか」には答えられません。 案Bでも「時間帯別ではどうか」「レシート1枚あたりの金額は」が出せなくなります。 集計は後からいくらでも粗くできますが、細かく戻すことはできません。
このため、基本は案A、つまり元データと同じ一番細かい単位で持ちます。
(データ量が大きい場合に、よく使う集計をあらかじめ計算して併用することはあります。前回の記事で触れた事前集計がそれに当たります。まず細かい粒度で残し、集計はその上に作る、という順番が基本です。)
ステップ4:ファクトテーブルとディメンションテーブルへの分割
粒度が決まったら、元データを2種類の表に分けます。 数値と参照だけを持つファクトテーブルと、切り口の情報を持つディメンションテーブルです。
ファクトテーブルは、明細1行を1行のまま、数値(メジャー)と各ディメンションへの参照に絞った形にします。
sales(ファクトテーブル。1行=レシートの中の1商品):
| receipt_no | date_id | time | store_id | product_id | sales_amount | quantity |
|---|---|---|---|---|---|---|
| 1001 | 20260701 | 08:12 | S01 | P01 | 480 | 1 |
| 1001 | 20260701 | 08:12 | S01 | P02 | 600 | 2 |
| 1002 | 20260701 | 08:15 | S02 | P03 | 400 | 1 |
商品や店舗の詳しい情報は、ディメンションテーブル側に持たせます。
products(商品ディメンション):
| product_id | product_name | category |
|---|---|---|
| P01 | カフェラテ | ドリンク |
| P02 | クロワッサン | フード |
| P03 | ブレンドコーヒー | ドリンク |
calendar(日付ディメンション):
| date_id | 年 | 月 | 日 | 曜日 | 祝日フラグ |
|---|---|---|---|---|---|
| 20260701 | 2026 | 7 | 1 | 水 | ✕ |
| 20260702 | 2026 | 7 | 2 | 木 | ✕ |
日付のためにわざわざ表を作るのは、遠回りに見えるところです。 ただ、「曜日」「祝日かどうか」「年度」といった情報は、日付の数字から毎回計算するより、表の列として持っておく方が扱いやすくなります。 曜日別の集計は「calendarの曜日列でグループ化する」だけになり、どのBIツールでも同じように使えます。
店舗のstoresも同じ要領で作ると、表は4つになります。 ファクトテーブルを中心に、ディメンションテーブルがつながる形です。
graph LR
P["products(商品)"] --- F["sales<br>ファクトテーブル"]
S["stores(店舗)"] --- F
C["calendar(日付)"] --- F
前回の記事でスタースキーマとして紹介した形が、ここで出来上がりました。 sales、products、stores、calendarという表の構成は、前回の記事の例と同じものです。
ステップ5:BIツールでの集計
この4つの表をBIツールに読み込み、表同士のつながり(product_idなどの参照)を設定すると、画面のフィールド一覧にディメンションの列とメジャーの列が並びます。
あとは操作だけです。
- 行に「店舗」、列に「月」、値に「金額の合計」を置くと、月別・店舗別のクロス集計表になる
- 「月」を掘り下げれば日別に、calendarの「曜日」に置き換えれば曜日別になる
ステップ1の要望「月ごとに、店舗ごとに、売上金額の合計を見たい」が、ここで画面になりました。 商品×店舗×日付の軸で金額と数量を集計できる状態、つまり前回の記事で説明したキューブが、この設計から出来上がっています。
(事前集計型(MOLAP)の製品であれば、この設計を元にキューブを構築します。データベースに都度問い合わせる型であれば、操作のたびにSQLが発行されます。前回の記事で整理した方式の違いはここに現れますが、ディメンションとメジャーを決めるまでの設計は、どの方式でも同じです。)
設計例:集計したいこと別のディメンションとメジャー
手順が一通り通ったので、要望のバリエーションで練習します。 同じカフェチェーンで、別の要望が出てきた場合の設計です。
| 集計したいこと | ディメンション | メジャー |
|---|---|---|
| 月別・店舗別の売上 | 日付(年>月)、店舗 | 金額の合計 |
| 曜日・時間帯別の売れ筋商品 | 日付(曜日)、時間帯、商品 | 数量の合計 |
| カテゴリ別の客単価 | 商品(カテゴリ)、日付 | 金額の合計 ÷ レシート枚数 |
| 年代別の人気商品 | 会員(年代)、商品 | 数量の合計 |
上の3つは、いま作った表でほぼ賄えます。
- 曜日 — calendarの曜日列をそのまま軸にする
- 時間帯 — salesのtime列から「朝(〜11時)」「昼(11〜14時)」のような区分を作り、時間帯ディメンションとして持つ
- レシート枚数 — receipt_noの種類数を数える。ステップ4でreceipt_noを残したのは、この種の集計のためです
4つ目の「年代別」だけは、いまの表では作れません。 元データの明細に、会員を特定する情報がないためです。 レジで会員カードを読み取り、明細に会員番号が残る仕組みがあって、初めて会員ディメンションを作れます。
元データに記録がない項目は、後からディメンションにもメジャーにもできません。 「何を集計したいか」を書き出す作業は、裏返すと「業務の中で何を記録しておくか」を決める作業でもあります。
よくある迷いどころ
■ 迷い1:単価はディメンションかメジャーか
「単価」のような数値の項目は、どちらに置くか迷いやすいところです。 判断の基準は、項目の種類ではなく使い方にあります。
- その数値を集計したい(平均単価の推移を見たい)→ メジャー
- その数値で絞り込み・グループ分けをしたい(500円以下の商品に絞りたい)→ 「〜500円」「500〜1,000円」のような価格帯を作り、商品ディメンションの属性にする
同じ単価という項目が、要望によってメジャーにも、ディメンションの材料にもなります。
■ 迷い2:合計できないメジャー
注意点: 単価や率は、そのまま合計・平均してはいけないメジャーです。
平均単価を出すとき、明細の単価列を単純に平均すると、1個しか売れていない商品と100個売れている商品が同じ重みになってしまいます。 正しくは「金額の合計 ÷ 数量の合計」です。 客単価も同じで、「金額の合計 ÷ レシート枚数」と、分子と分母を別々のメジャーとして持ち、割り算は表示のときに行います。
在庫数のような「その時点の残高」も、月をまたいで合計すると意味のない数値になります(7月の在庫と8月の在庫を足しても、何の量でもありません)。 メジャーを決めるときは、「この数値は合計して意味があるか」を確認しておくと、集計結果の事故を防ぎやすくなります。
■ 迷い3:ディメンションが細かすぎる
会員別の分析がしたいからと、会員ID(10万人分)をそのまま軸にすると、10万行の集計表ができるだけで、比較になりません。 軸にするのは、年代、地域、会員ランクのような、並べて比較できる粗さの属性です。 一方で、ファクトテーブルの明細には会員番号をそのまま残します。 記録は細かく、見せる軸は粗く、という分担です。
■ 迷い4:1つのファクトテーブルへの詰め込み
売上のファクトテーブルに在庫や仕入の数値も入れたくなりますが、これらは記録される単位(粒度)が違う、別の業務の記録です。 売上は「レシートの明細ごと」、在庫は「日×店舗×商品ごと」のように、業務ごとにファクトテーブルを分けます。 その際、商品・店舗・日付のディメンションテーブルを両方から共有しておくと、「商品別に売上と在庫を並べる」といった横断の集計ができます。
この手順の呼び名
ここまでの手順は、この記事のための便法ではなく、データウェアハウス設計の分野で確立された方法の入門版です。 ディメンショナルモデリング(次元モデリング)と呼ばれます。
この分野の代表的な教科書『The Data Warehouse Toolkit』の著者Ralph Kimballは、設計を次の4ステップで進めると整理しています。
① 業務プロセスの選択(どの業務の記録を対象にするか) ② 粒度の宣言(ファクトテーブルの1行が何を表すか) ③ ディメンションの特定 ④ ファクトの特定(メジャーにする数値の確定)
この記事のステップ1が①に、ステップ3が②に、ステップ2が③④に対応します。 正式な手順では、ディメンションより先に粒度を決めます。 すべての切り口と数値が「1行=レシートの中の1商品」という宣言に矛盾しないかを、先に固定するためです。 慣れてきたら、粒度から考える順番に移ると、設計が安定します。
まとめ
キューブの設計は、業務の記録(元データ)と「集計したいこと」の文の2つを材料に進みました。 文の中の「〜ごとに」がディメンションを、「見たい数値」がメジャーを教えてくれて、粒度を一番細かい単位に決めれば、あとはファクトテーブルとディメンションテーブルに分けるだけです。
順序としては分析の設計が後ですが、逆向きの関係もあります。 「年代別の人気商品」の例のように、集計したいことを書き出してみると、業務の中でまだ記録できていない項目が見つかります。 分析の要望が、データの集め方を決めていく関係です。
(実務のディメンショナルモデリングには、商品のカテゴリが変わったとき過去の集計をどう扱うか(ディメンションの変更履歴の管理)など、この記事で扱っていない論点があります。一歩進む際は、参考に挙げたKimballグループの資料が詳しいです。)
自分のデータで最初のキューブを設計するときの、足がかりになれば嬉しいです。
参考
一次情報:
- Four-Step Dimensional Design Process(Kimball Group) — 設計4ステップの原典
- Grain(Kimball Group) — 粒度の考え方
- ウェアハウスでのディメンション テーブルのモデリング(Microsoft Learn)
読み物:
- スタースキーマ(基礎)(Zenn) — スタースキーマ設計の日本語での詳しい解説
- 前回の記事:BIツールの「キューブ」とは?リレーショナルデータベースとの関係からざっくり理解する