月次の経営会議の前日、営業本部長から電話が来ます。「先月の売上、Tableauのダッシュボードでは3億2,000万、経理のExcelでは3億1,500万になっている。どっちを出せばいいんだ」。調べると、Tableauの計算式はキャンセル分を引いておらず、経理はキャンセルを除いたうえで計上日を出荷日にしていました。どちらも間違いではありません。「売上」の決め方が2つあっただけです。翌月はLookerを使う部署との間で同じことが起き、データチームは毎月、会議の前に数字の突き合わせに追われています。
セマンティックレイヤーは、「売上」「注文件数」「平均単価」のような指標の定義を、BIツールの外で1か所にまとめる層です。BIもExcelも社内アプリも、そこに問い合わせて同じ定義の数字を受け取ります。どのツールを選ぶかは、数字が割れている場所がどこかで決まります。
状況別の早見表:数字が割れている場所で当たりをつける
| 数字が割れている場所 | 最初に検討するもの | 選んだあとで困りやすいこと |
|---|---|---|
| TableauやPower BIなど既存のBI同士。変換はdbtで書いている | dbt Semantic Layer | dbtの有料プラン(StarterかEnterprise)が要る |
| BIの外。社内アプリ、組み込みの分析画面、AIエージェントにも同じ数字を出したい | Cube | dbtとは別に、Cubeのデータモデルを書いて保守する |
| BIそのものが無い、または入れ替えたい。dbtを使っている | Lightdash | 大企業向けの細かい権限管理は、専用のBIほど揃っていない |
| Lookerの中だけで完結している | まずLookMLのままでよい | 他のBIから同じ定義を使いたくなったときに移行が要る |
| dbtを使っていない | Cube | 定義をどこで管理するか、別にルールが要る |
3つは同じ棚に並ぶ製品ですが、解こうとしている場所が違います。dbt Semantic Layerはdbtの中に定義を置いて既存のBIに配ります。CubeはAPIで外に配ることを得意とします。LightdashはBIまで一体で持ちます。
ツールより先に、「売上」を文章で決める
セマンティックレイヤーを入れても、定義そのものが決まっていなければ、割れた数字が1つの間違った数字になるだけです。最初の1か月は、ツールを触る前に定義書を作ります。紙1枚で足ります。冒頭の会社なら、次のように書きます。
| 項目 | 記入例 |
|---|---|
| 指標の名前 | 売上(税抜) |
| 計算式 | 税抜の受注金額の合計。状態が「出荷済み」「完了」の注文だけを数え、キャンセルと返品は除く |
| いつの売上とするか | 出荷日 |
| 含めないもの | 社内向けの取引、テスト用の注文 |
| 決める人 | 経理部長(変えるときは経理部長の承認を取る) |
| 主に使う場面 | 月次の経営会議、営業部門の予算管理 |
「決める人」の欄が埋まらない指標は、セマンティックレイヤーに載せても半年後に揉め直します。経理が決めるのか、営業企画が決めるのかを、ここで名前まで書きます。
最初に載せるのは、毎月の会議で数字の突き合わせが起きている5〜10個の指標だけで十分です。全部を移そうとすると、定義の合意だけで半年が過ぎます。
数字の突き合わせに、年いくら払っているか
稟議では、いまかかっている手間を金額にしておきます。冒頭の会社の数字で見積もります。時間の数字は説明のための仮定です。
| 項目 | 仮定 | 年間の時間 |
|---|---|---|
| 会議前の数字の突き合わせ | 3人 × 月6時間 × 12か月 | 216時間 |
| 新しいダッシュボードを作るたびの集計式の書き直し | 年10本 × 1本8時間 | 80時間 |
| 合計 | 296時間 |
担当者の年収を600万円とすると、会社が負担する総コストはその約3倍の1,800万円です。年1,900時間で割ると時給は約9,500円で、296時間なら年約280万円になります。これに、会議の冒頭で「どっちの数字が正しいのか」を議論する役員の時間が加わります。
dbt Semantic Layerは、dbtの中に定義を置いて既存のBIに配る
dbtで変換を書いているなら、最も自然な選択肢です。追加で覚えることが少なく済みます。指標の定義をdbtのモデルの隣にYAMLで書き、MetricFlowというエンジンがその定義からSQLを組み立てます。MetricFlowは2025年10月にApache 2.0ライセンスで公開されています。
dbtの最新の書き方(dbt v1.12以降)では、モデルの定義の中に指標を書きます。
models:
- name: fct_orders
semantic_model:
enabled: true
agg_time_dimension: shipped_at
columns:
- name: order_id
entity:
type: primary
name: order
- name: shipped_at
granularity: day
dimension:
type: time
- name: order_status
dimension:
type: categorical
metrics:
- name: net_revenue
label: 売上(税抜)
type: simple
agg: sum
expr: amount_excl_tax
filter: "{{ Dimension('order__order_status') }} in ('shipped', 'completed')"
- name: order_count
label: 注文件数
type: simple
agg: count
expr: 1
- name: avg_order_value
label: 平均注文単価
type: ratio
numerator: net_revenue
denominator: order_count
定義書の「出荷済み・完了だけを数える」「出荷日で数える」が、そのままコードの filter と agg_time_dimension になっているのが分かります。定義書とコードを1対1で対応させておくと、経理部長に「この行があなたの決めた定義です」と見せられます。
外部からはGraphQL API、JDBC API、Python SDKで問い合わせます。公式ドキュメントでは、Power BI、Tableau、Google Sheets、Microsoft Excel、Hex、Modeなどとの連携が案内されています。注意点は契約です。指標を定義して問い合わせるには、dbtのStarterかEnterprise系のプランが必要だと公式に書かれています。
Cubeは、BIの外にも同じ数字を配りたいときに選ぶ
Cubeは、指標の定義をAPIとして公開するセマンティックレイヤーです。問い合わせの窓口が多いのが特徴で、Postgres互換のSQL API、REST API、GraphQL API、Power BI向けのDAX APIがあります。社内アプリの分析画面やAIエージェントから、BIと同じ定義の数字を取りたいときに効きます。
定義はYAMLで書きます。dbtのモデルを読み込むための cube_dbt パッケージもあります。
cubes:
- name: orders
sql_table: gold.fct_orders
measures:
- name: net_revenue
sql: amount_excl_tax
type: sum
filters:
- sql: "{CUBE}.order_status IN ('shipped', 'completed')"
- name: count
type: count
dimensions:
- name: order_id
sql: order_id
type: number
primary_key: true
- name: shipped_at
sql: shipped_at
type: time
pre_aggregations:
- name: daily_revenue
measures:
- CUBE.net_revenue
- CUBE.count
time_dimension: CUBE.shipped_at
granularity: day
refresh_key:
every: 1 hour
最後の pre_aggregations は、よく使う集計を前もって作っておく仕組みです。集計結果はCube Storeという専用の保存先に置かれ、問い合わせがその集計で答えられるときは、DWHに行かずにそこから返します。社外向けの画面のように、同時に多くの人が見る用途で効きます。最初から作り込む必要はありません。応答が遅い問い合わせが出てから足します。
選ぶときは、dbtの定義とは別にCubeのデータモデルを保守する覚悟が要ります。dbtで列名を変えたらCube側も直す、という手間が残ります。
Lightdashは、BIごとdbtに寄せたいときに選ぶ
Lightdashは、dbtのYAMLに書いた指標をそのまま読んで、BIとして見せるツールです。dbtのschema.ymlに数行足すだけで指標ができるので、dbtを書いているエンジニアがBIも兼ねている小〜中規模のチームに向きます。
models:
- name: fct_orders
columns:
- name: amount_excl_tax
config:
meta:
metrics:
net_revenue:
type: sum
label: 売上(税抜)
filters:
- order_status: ['shipped', 'completed']
dbt 1.10以降は config: meta: の下に、1.9以前は meta: の下に書きます。2026-10-17時点の公式の料金ページでは、Cloud Proが月3,000ドルで利用者数による課金はなく、自社で動かすオープンソース版もあります。既存のTableauやPower BIを残したまま指標をそろえたい場合には向きません。使いどころと運用の勘どころはLightdashとはにまとめています。
どれを選んでも、Gold層の設計は残る
セマンティックレイヤーを入れても、集計の土台になるテーブルの設計は要ります。dbtで集めて整えたテーブル(メダリオン構成でいうGold層)の上に、定義の層を薄く載せる形が基本です。
| 層 | 役割 | 冒頭の会社での例 |
|---|---|---|
| Gold層のテーブル(dbt) | 指標の材料になる行を、使いやすい粒度で用意する | 注文1件1行で、税抜金額・出荷日・状態を持つテーブル |
| セマンティックレイヤー | 指標の定義を持つ | 売上(税抜)=出荷済み・完了の注文の税抜金額の合計 |
| BI・アプリ・AI | 定義に問い合わせて表示する | 経営会議のダッシュボード、営業向けの社内アプリ |
Gold層を省いて複雑な結合をセマンティックレイヤーに任せると、生成されるSQLが重くなります。層の分け方はメダリオンアーキテクチャとdbtの3層構造、指標そのものの選び方はKPI設計で扱っています。
導入は「割れている指標を1つ」から
| 時期 | やること | 終わったと言える目安 |
|---|---|---|
| 1か月目 | 会議で突き合わせが起きている指標を5〜10個挙げ、定義書を書いて決める人の承認を取る | 定義書に「決める人」の名前が全部入っている |
| 2か月目 | 一番揉めている指標1つを、選んだツールに載せる | ツールが返す数字と、経理の数字が一致する |
| 3か月目 | その指標を見ているダッシュボードを、セマンティックレイヤー経由に切り替える | 会議前の突き合わせが、その指標について無くなる |
| 4か月目以降 | 残りの指標を1つずつ移す | 新しいダッシュボードで集計式を書かなくなる |
2か月目で経理の数字と一致しないときは、ツールより先に定義書を疑います。よくあることです。たいていは「含めないもの」の欄に書き漏れがあります。
よくある質問(FAQ)
LookerのLookMLもセマンティックレイヤーですか?
LookMLも指標の定義を1か所に持つ仕組みです。Lookerの中だけで使うなら、LookMLのままで足ります。他のBIや社内アプリからも同じ定義を使いたくなったときに、BIの外に定義を置くツールが候補になります。
dbt CoreだけでSemantic Layerは使えますか?
MetricFlowはApache 2.0ライセンスで公開されているので、定義を書いてローカルで問い合わせるところまでは無料で動きます。しかし、BIから接続するためのAPI(GraphQL、JDBC)や、Tableau・Power BIなどとの連携は、dbtのStarterかEnterprise系のプランで提供されます。既存のBIに配りたいなら、有料プランを前提に予算を組みます。
セマンティックレイヤーがあれば、Gold層のテーブルは要らなくなりますか?
要ります。セマンティックレイヤーが持つのは指標の定義で、その材料になるテーブルはdbtなどで用意します。Gold層で粒度と列をそろえておけば、指標の定義は短く済み、生成されるSQLも軽くなります。Gold層を省くと、重い結合を毎回の問い合わせで行うことになります。
AIエージェントに数字を答えさせるときにも必要ですか?
効果は大きいです。AIに自由にSQLを書かせると、キャンセルを含めるかどうかのような社内の決まりを知らないまま集計します。セマンティックレイヤーに問い合わせさせれば、定義書どおりの数字が返ります。CubeのREST・GraphQL APIや、dbt Semantic LayerのAPIを、AIが呼ぶ窓口にします。
指標の定義は誰が持つべきですか?
定義を決めるのは業務側、コードに落とすのはデータ側、と分けます。売上なら経理部長、受注件数なら営業企画、のように指標ごとに決める人を1人決め、定義書に名前を書きます。ツールを入れても決める人がいなければ、定義の変更をめぐって同じ議論を繰り返します。
出典
- dbt Docs: dbt Semantic Layer(2026-10-17 参照:指標を定義して問い合わせるにはStarterかEnterprise系のプランが必要)
- dbt Docs: Semantic Layer APIs(2026-10-17 参照:GraphQL API、JDBC API、Python SDK)
- dbt Docs: Available integrations(2026-10-17 参照:Power BI、Tableau、Google Sheets、Microsoft Excel、Hex、Modeなどの連携先)
- dbt Docs: Latest metrics YAML spec(2026-10-17 参照:dbt v1.12以降の新しい書き方(semantic_model、columns上のentity/dimension、agg_time_dimension、measuresの非推奨))
- dbt Docs: Simple metrics(2026-10-17 参照:simple metricのagg/expr/filterの書き方)
- dbt Docs: Ratio metrics(2026-10-17 参照:ratio metricのnumerator/denominatorの書き方)
- dbt Labs Blog: Open sourcing MetricFlow(2026-10-17 参照:2025年10月(Coalesce 2025)にMetricFlowをApache 2.0で公開)
- PyPI: metricflow(2026-10-17 参照:Apache 2.0ライセンス、dbt-metricflowで導入しdbtプロジェクトとアダプタが必要)
- Cube Docs: Core Data APIs(2026-10-17 参照:SQL API(Postgres互換)、REST API、GraphQL API、DAX API(Power BI向け))
- Cube Docs: Pre-aggregations(2026-10-17 参照:pre_aggregationsのYAMLの書き方、集計結果がCube Storeに保存されること)
- Cube Docs: Introduction(2026-10-17 参照:Cube Coreがオープンソースのセマンティックレイヤーであること、事前集計とCube Storeによるキャッシュ)
- Cube Docs: cube_dbt package(2026-10-17 参照:dbtのmanifestを読み込んでCubeのモデルにするパッケージ)
- Lightdash Docs: Metrics reference(2026-10-17 参照:dbtのYAMLでの指標定義、dbt 1.10以降はconfig: meta、filtersの書き方(リストはIN))
- Lightdash: Pricing(2026-10-17 参照:Cloud Proが月3,000ドルで利用者数課金なし、オープンソース版のセルフホスト)
会議のたびに起きる「どっちの売上が正しいのか」を終わらせる定義書づくりから、一緒に始めませんか。初回相談(30分・無料)で一緒に整理できます。