Snowflake

Snowflake のセマンティックビューで、集計の決まりを AI に渡す

集計の決まりを、AI が読める場所に置く
Ryosuke Ishii

AI に集計を頼むと、SQL はすぐに書いてくれます。ただ、その集計が自分たちの決まりどおりかは別の話です。「保存率」をどう計算するか、月の区切りをどこにするか、目標に届いたかをどう判定するか。こうした決まりを Snowflake の中に書いておき、AI にも BI にも同じ決まりで答えさせる。そのために作ったのがセマンティックビューです。

集計の決まりを、AI が読める場所に置く
集計の決まりを、AI が読める場所に置く

AI が書く SQL は、決まりを知らない

題材にしたのは、一番飯店の Instagram の月次レポートです。毎月、投稿数・リーチ・保存率などを集計して、目標に届いたかを判定しています。

このレポートには、表を見ただけでは分からない決まりがいくつもあります。たとえば保存率は「月の保存の合計 ÷ 月のリーチの合計」で、投稿ごとの保存率を平均したものではありません。リーチや保存は日々増えていく累計の値なので、「投稿した月の翌月1日 23:59:59 時点の値」に固定して数えます。

AI に「6月の保存率は?」と聞くと、投稿ごとの保存率を平均した SQL を書くことがあります。SQL としては正しく動き、数字も出ます。ただ、レポートとは違う数字です。決まりを知らないまま、それらしい答えを返してしまうのが一番困るところでした。

なぜセマンティックビューが要るのか

一度きりの集計なら、人が SQL を見直せば済みます。困るのは、AI がその場で SQL を書き、その答えを人がそのまま使う場面です。お客様の案件で作っている次の2つで、そのことがはっきりしました。

AI のダッシュボードも試算も、同じ定義を読む
AI のダッシュボードも試算も、同じ定義を読む

AI に聞けるダッシュボード

経営の数字を日本語で聞くと、AI が SQL を書いて答え、グラフも描くダッシュボードです。ここでは質問のたびに新しい SQL が書かれます。同じ「売上」でも、聞き方しだいで集計の範囲や月の区切りが変わるおそれがあります。

画面に並ぶグラフと AI の答えの数字が違えば、どちらも信用されなくなります。そこで、指標の定義はお客様のセマンティックビューに置き、AI への指示はその定義から作るようにしました。定義が変われば、AI への指示も1時間ごとに作り直されます。

答えが合っているかを確かめる試験でも、正解はセマンティックビューに直接問い合わせた結果にしています。画面・AI・試験が、同じ物差しで測られることになります。

利益を試算するシミュレーション

もう1つは、KPI を動かしたときに利益がどう変わるかを試算するシミュレーションです。ここでは元になる数字の定義が少しでもずれていると、そこから動かした試算も、すべて同じようにずれます。

試験で実際に困ったのは、年度の数え方でした。年度は4月始まりなので、「M6」は9月です。ところが AI は「M6」を6月と読みました。AI への指示に「M1 は4月」と書いても、守られないことがありました。

そこで、月の読み替えや単位の換算はプログラムで済ませてから AI に渡しています。そのうえで、何が正しい数字かはセマンティックビューで決める、と役目を分けました。AI への指示は確率でしか効かないので、正しさの基準は AI の外に置く必要があります。

正しい数字を1か所で決める

どちらにも共通するのは、「何が正しい数字か」を1か所で決めておく必要があることです。セマンティックビューは、その1か所を Snowflake の中に持てる仕組みです。AI も BI も試験も同じ定義を読むので、どれか1つだけが違う数字を出す、ということが起きにくくなります。

セマンティックビューに書けるもの

セマンティックビューは、表の上に「この列は何を意味するか」「この指標はどう計算するか」を書いておく Snowflake の仕組みです。中身は大きく分けて4つあります。

  • 事実と切り口:リーチ・保存などの数値(事実)と、投稿月・投稿の種類などの切り口
  • 指標:保存率や判定のように、集計してから計算するもの。計算式をここに1つだけ持つ
  • AI への指示:AI が SQL を作るときに守ってほしいことを文章で書く欄と、「この質問にはこの SQL」という手本

指標の計算式をセマンティックビューに1つだけ持たせておけば、AI に聞いても、BI から引いても、同じ式で計算されます。人によって、道具によって数字が変わる、ということがなくなります。

作ったセマンティックビューは、Snowsight(Snowflake の画面)の「AI と ML」→「Cortex アナリスト」から開いて、中身を確かめられます。指標ごとに、説明・計算式・同義語が並びます。

Snowsight で開いたセマンティックビュー。指標ごとに説明と計算式が並ぶ
Snowsight で開いたセマンティックビュー。指標ごとに説明と計算式が並ぶ

画面の「MONTHLY_SAVE_RATE」が、月の保存率の指標です。説明に「投稿ごとの保存率の平均ではない」と書き、計算式は「月の保存合計 ÷ 月のリーチ合計 × 100」にしています。

題材:月次レポートの集計条件

月次レポートを作っているプログラムを読み、集計条件を拾い出しました。セマンティックビューには、次のような形で書き込んでいます。

  • 指標と判定:投稿数(目標9本)・リール本数・保存率・月間リーチなどを指標にし、それぞれ「達成/改善中/未達」の判定も指標として持たせた
  • 説明欄:各指標の説明に【条件】【判定】と書き、計算のしかたと境目の値を残した
  • AI への指示:月の区切り、時差を補正しないこと、保存率を平均しないこと、目標値、データが無い項目への答え方など8項目を書いた

下ごしらえとして、元の表から「1投稿 = 1行、数字は翌月1日 23:59:59 時点」のビューを先に作り、セマンティックビューはその上に載せました。累計の値を何度も合計し直してしまう事故を、元の段階で防ぐためです。

Claude から作ると、CREATE が通らない

作業は Claude に頼み、Claude から Snowflake へは MCP(AI が外の道具を使うための接続口)でつないでいます。最初に、セマンティックビューを作る SQL(CREATE SEMANTIC VIEW)を送ったところ、次のように断られました。

Statement type of Unknown is not allowed.

MCP の側で、送ってよい SQL の種類を設定で絞っています。CREATE SEMANTIC VIEW は新しい構文のため、その仕分けで「種類不明」に分類され、通りませんでした。2026年10月30日に試し直しても同じでした。

代わりに使ったのが、YAML(設定を書くための書式)からセマンティックビューを作る呼び出しです。

CALL SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML(
  'ORDER_SYSTEM.SEMANTIC_SANDBOX',
  $$
name: ICHIBAN_INSTAGRAM_SV
tables:
  - name: posts
    base_table: {database: ORDER_SYSTEM, schema: SEMANTIC_SANDBOX, table: V_IG_POST_MONTHLY_BASIS}
    ...
  $$,
  TRUE   -- TRUE は検査だけ。FALSE で作る
);

これは CALL 文なので、MCP の設定を変えずに通ります。3つ目の引数を TRUE にすると、中身を検査するだけで何も作りません。「検査で通る → FALSE にして作る」の順にすれば、作ってから壊れていたと気づくことがありません。

CREATE が通らないので、YAML から作る
CREATE が通らないので、YAML から作る

Snowsight でセマンティックビューを開くと、右上の「YAML」に切り替えて、同じ中身を YAML の形で見ることもできます。Claude から渡した YAML と同じ形なので、画面で見比べながら直せます。

同じセマンティックビューを YAML の形で見たところ
同じセマンティックビューを YAML の形で見たところ

なお、画面で開いたときに「このセマンティックビューを所有していません」と注意が出ることがあります。作った役(ロール)と開いた役が違うときです。写しを見ることはできますが、画面から直して反映するには、作った役で開く必要があります。

落とし穴1:集計の名前と、元の列の名前がぶつかる

検査の段階で、次のエラーが出ました。

Invalid fact definition for 'POSTS.POST_SAVE_RATE_PCT':
A fact cannot refer to another aggregate-level expression
that is defined at its own or a lower level of granularity.

「事実が、集計した値を参照している」という内容です。ところが、POST_SAVE_RATE_PCT は元のビューの列 SAVE_RATE_PCT(投稿ごとの保存率)をそのまま指しているだけで、集計はしていません。

原因は名前でした。月の保存率を計算する指標に、元の列と同じ save_rate_pct という名前を付けていたのです。セマンティックビューの中では、指標の名前が元の列の名前より先に解釈されます。そのため、事実の式に書いた SAVE_RATE_PCT が、元の列ではなく同じ名前の指標(集計した値)を指してしまいました。

指標の名前を monthly_save_rate に変えると、検査が通りました。10月30日に、検査だけのモードで同じエラーが出ることを確かめ直しています。指標には、元の列と重ならない名前を付けておくのが安全です。

落とし穴2:時刻は最初から日本時間だった

月の区切りを決めるとき、投稿日時の列を「世界標準時で入っているはず」と考え、9時間足して日本時間にしかけました。

念のため、投稿時刻を時間ごとに数えてみると、投稿は夕方から夜に集中していました。もし世界標準時で入っていたなら、日本時間では早朝の投稿ばかりになります。店の投稿の実態とは合いません。元の列は、最初から日本時間で入っていました。

9時間足していたら、月末の夜の投稿が翌月に数えられていたことになります。このことは、投稿月の説明欄と AI への指示の両方に「日本時間なので補正しない」と書きました。AI が同じ思い込みで補正しないようにするためです。

公開しているレポートと突き合わせる

最後に、セマンティックビュー経由で集計した数字を、公開している月次レポートと突き合わせました。セマンティックビューは、SEMANTIC_VIEW という関数で、切り口と指標を名前で指定して引けます。

SELECT * FROM SEMANTIC_VIEW(
  ORDER_SYSTEM.SEMANTIC_SANDBOX.ICHIBAN_INSTAGRAM_SV
  DIMENSIONS posts.post_month
  METRICS posts.post_count, posts.total_reach, posts.monthly_save_rate, posts.save_rate_judgement
  WHERE posts.post_month BETWEEN '2026-05-01' AND '2026-07-01'
);

2026年5月〜7月の3か月は、レポートと全項目が一致しました。4月以前は当時の取り方が違い、8月以降は Snowflake への取り込みを止めているため一致しません。この「一致を確かめた期間」も、絞り込みの条件としてセマンティックビューに入れてあります。

まとめ

  • AI がその場で SQL を書くダッシュボードや試算では、正しい数字の基準を AI の外に1か所置く必要がある。集計の決まり(計算式・月の区切り・目標と判定)をセマンティックビューに書いておけば、AI にも BI にも同じ決まりで答えさせられる
  • Claude から MCP 経由で作るとき、CREATE SEMANTIC VIEW が通らなければ、YAML から作る呼び出しを使う。TRUE で検査してから FALSE で作る
  • 指標の名前を元の列の名前と重ねない。時刻の列が何時間ずれているかは、思い込まずにデータで確かめる
ABOUT ME
石井 亮介(りょうさん)
石井 亮介(りょうさん)
データパレード 代表取締役
㈱データパレードの代表取締役で、高田馬場の町中華「一番飯店」のChief Data Officerも務めています。BIツールのセールスエンジニア・システムエンジニア・カスタマーサクセス歴15年。大学のデータサイエンス教育で講師も担当してきました。現在は自社業務のほとんどをAIに移管し、AI10部署と50を超える自動処理が24時間動く「AI経営」を実践中。その実践知をこのブログで発信しています。
記事URLをコピーしました