
この記事はノバセル テクノ場 出張版2025 Advent Calendar 2025の20日目の記事です。
はじめに
ノバセルで PdM をしていた山中です。現在は親会社のラクスルへ出向しており、全社の AI 活用推進を担当しています。
データ分析の現場では、SQL を書ける人材が限られていることや、ドメイン知識が属人化していることが課題となっています。「このカラムの値 1 は何を意味するのか」「このテーブルとあのテーブルはどう結合すればいいのか」といった暗黙知が散在しており、データ分析のたびに有識者へ確認しなければならない状況が生まれがちです。
一方で、ChatGPT や Claude に「売上データを分析して」と投げかけるとどうでしょうか。テーブル構造やカラムの意味を理解していないため、的外れなクエリが生成されたり、誤った結合条件で集計されたりと、実用的でない結果になりがちです。
かといって、データカタログツールやセマンティックレイヤー(Looker 等)を導入するのは追加ライセンスコストがかかることもあり、なかなか踏み切れないこともあります。
そこで今回は、最近提供が開始された BigQuery MCP と Claude Skills を組み合わせて、ドメイン知識をクイックに AI へ注入しながらデータ分析を自動化してみます。
準備編
BigQuery MCP とは
BigQuery MCP は、BigQuery のテーブル定義やメタデータを AI から参照できるようにする MCP サーバーです。Claude などのアシスタントが MCP ツール経由でテーブル一覧の取得、スキーマ情報の照会、クエリの実行といった操作を行えるようになります。公式が提供しているリモート MCP サーバーになります。
BigQuery MCP では、以下の 5 つのツールが利用可能です(詳細はこちら):
| ツール名 | 機能 |
|---|---|
| list_dataset_ids | プロジェクト内のデータセット ID 一覧を取得 |
| get_dataset_info | 特定のデータセットの詳細情報を取得 |
| list_table_ids | データセット内のテーブル ID 一覧を取得 |
| get_table_info | テーブルのスキーマとメタデータを取得 |
| execute_sql | SQL クエリを実行して結果を取得 |
BigQuery MCP を利用するには、Google Cloud のプロジェクト設定と OAuth 認証の構成が必要です。基本的な手順は 公式ドキュメント に詳しく記載されています。
今回は、Claude Desktop と接続しました。チャットで利用するモデルは Sonnet 4.5 です。
補足:MCP Toolbox for Databases について
なお、MCP Toolbox for Databases を利用すると、標準の BigQuery MCP に加えて、貢献度分析や予測分析などの高度な機能が利用可能になります。 Conversational Analytics API も含めて呼び出し可能なので、リモート MCP に拘らない場合には、こちらの利用も検討してください。
Claude Skills とは
Claude Skills は、特定のドメイン知識や作業手順を Claude に教え込むための仕組みです。Markdown 形式でスキルファイルを作成し、Claude Desktop に読み込ませることで、AI が文脈に応じて適切な知識を参照しながら作業を進められるようになります。
今回作成したスキル
データ分析の領域ではデータセットに関する情報が膨大に存在し、AI に渡すコンテクストの選別が難しいという課題があります。 そこで、今回は必要なドメイン知識だけがロードされる Progressive Disclosure の効果も検証します。 以下の 6 つのスキルを作成しました。
| スキル | 役割 |
|---|---|
| bigquery-mcp | MCP ツールの使い方 |
| bigquery-ec-values | EC データのカラム値定義(order_status, user_type など) |
| bigquery-ec-relations | EC データのテーブル結合パターン |
| bigquery-marketing-values | マーケティングデータのカラム値定義(channel, status など) |
| bigquery-marketing-relations | マーケティングデータのテーブル結合パターン |
| artifact-charts | グラフ描画用テンプレート |
検証用データセット
EC 売上データ(demo_ec_sales)
| テーブル | 説明 |
|---|---|
| orders | 注文情報 |
| order_items | 注文明細 |
| products | 商品マスタ |
| users | ユーザー情報 |
ドメイン知識の例:
order_status = 4→ 配達完了user_type = 2→ プレミアム会員- 売上集計時はキャンセル(order_status = 9)を除外
マーケティングデータ(demo_marketing)
| テーブル | 説明 |
|---|---|
| campaigns | 広告キャンペーン情報 |
| ad_impressions | 広告表示ログ |
| ad_clicks | 広告クリックログ |
| conversions | コンバージョン情報 |
ドメイン知識の例:
status = 3→ 終了済みキャンペーンchannel = 'google_ads'→ Google 広告- ROAS = revenue / cost
スキルの構築
スキルは、Claude と対話しながら作成することが可能です。
各スキルのソースコードは、以下のリポジトリをご覧ください。
検証編
以下の依頼文を使って、スキルの有無による精度の違いを検証しました。
プレミアム会員の先月の完了注文の売上を商品カテゴリ別に集計してください
検証 1: bigquery-mcp のみ
BigQuery MCP だけを有効化した状態で依頼を投げてみました。
以下は、bigquery-mcp.md の概要です。
--- name: bigquery-mcp description: "BigQuery MCP ツールのエキスパート。データ探索、スキーマ確認、SQL クエリ実行に使用。BigQuery のデータセット、テーブル、分析クエリの実行時にトリガー。" --- # BigQuery MCP ツールガイド ## 概要 BigQuery MCP は以下の 5 つのツールを提供: - **list_dataset_ids** - プロジェクト内のデータセット一覧 - **get_dataset_info** - データセットのメタデータ取得 - **list_table_ids** - データセット内のテーブル一覧 - **get_table_info** - テーブルスキーマとメタデータ取得 - **execute_sql** - SQL クエリ実行 ## ツール選択ガイド | 目的 | ツール | 使用場面 | |------|--------|----------| | データ探索 | `list_dataset_ids` | 最初のステップ:どのデータセットがあるか確認 | | データセット詳細 | `get_dataset_info` | 説明、ラベル、ロケーション取得 | | テーブル探索 | `list_table_ids` | 特定データセット内のテーブル一覧 | | スキーマ確認 | `get_table_info` | カラム名、型、説明を取得 | | データ取得 | `execute_sql` | SELECT、集計、結合クエリ実行 | ## 推奨ワークフロー 1. list_dataset_ids └─> 対象データセットを特定 2. list_table_ids(dataset_id) └─> 関連テーブルを探索 3. get_table_info(dataset_id, table_id) └─> クエリ前にスキーマ確認 4. execute_sql(query) └─> 最適化したクエリを実行 ...(以降省略)
かろうじて BigQuery を利用することは察してくれたようですが、参照するべきプロジェクト ID やデータセットを知らないため、回答できませんでした。

検証 2: bigquery-ec-relations を追加
EC データに関するリレーションスキルを追加してみました。
--- name: bigquery-ec-relations description: "EC サイト BigQuery テーブルの結合パターン定義。orders, order_items, products, users テーブル間のリレーションと推奨 JOIN 条件を提供。売上集計、顧客分析時に使用。" --- # BigQuery テーブル結合パターン ## 対象データセット - **プロジェクト:** `demo-project` - **データセット:** `demo_ec_sales` | テーブル | 説明 | |----------|------| | orders | 注文情報 | | order_items | 注文明細 | | products | 商品マスタ | | users | ユーザー情報 | ## テーブル構成 users (1) ──── (N) orders (1) ──── (N) order_items (N) ──── (1) product ## 基本の結合条件 | From | To | 結合キー | 関係 | |------|----|---------|------| | orders | order_items | order_id | 1:N | | order_items | products | product_id | N:1 | | orders | users | user_id | N:1 | ...(中略)... ## 注意事項 - 売上集計時は必ず `order_status != 9` でキャンセルを除外 - 売上金額は `oi.quantity * oi.price` で計算 - order_items は必ず orders 経由で結合(直接 users と結合しない)
スキルをロードして、今回は適切にプロジェクトIDやデータセットの中を確認することができています。
-- 生成されたクエリ SELECT p.category_name, COUNT(DISTINCT o.order_id) AS order_count, SUM(oi.quantity) AS total_quantity, SUM(oi.quantity * oi.price) AS total_sales FROM `demo-project.demo_ec_sales.orders` o INNER JOIN `demo-project.demo_ec_sales.order_items` oi ON o.order_id = oi.order_id INNER JOIN `demo-project.demo_ec_sales.products` p ON oi.product_id = p.product_id INNER JOIN `demo-project.demo_ec_sales.users` u ON o.user_id = u.user_id WHERE u.user_type = 2 AND o.order_status != 9 AND o.order_date >= '2025-11-01' AND o.order_date < '2025-12-01' GROUP BY p.category_name ORDER BY total_sales DESC
JOIN は正しく生成されましたが、いくつか問題があります。
- 「プレミアム会員」の条件(
user_type = 2)を推定している。またそのために多くのクエリを発行している - 「完了注文」の条件(
order_status = 4)ではなく、キャンセル除外(!= 9)のみ

検証 3: bigquery-ec-values を追加
EC データに関する値の定義スキルを追加してトライしてみます。
--- name: bigquery-ec-values description: "EC サイト BigQuery テーブルのカラム値定義。order_status や user_type などの数値コードとビジネス用語の対応を提供。売上分析、注文ステータス、会員種別の質問時に使用。" --- # BigQuery カラム値定義 ## orders テーブル ### order_status | 値 | 意味 | ビジネス用語 | |----|------|-------------| | 1 | 受注済み | 新規注文 | | 2 | 出荷準備中 | 処理中 | | 3 | 出荷済み | 配送中 | | 4 | 配達完了 | 完了 | | 9 | キャンセル | キャンセル | **よく使う条件:** - 完了注文: `order_status = 4` - キャンセル除外: `order_status != 9` - アクティブ注文: `order_status IN (1, 2, 3)` ## users テーブル ### user_type | 値 | 意味 | |----|------| | 1 | 一般会員 | | 2 | プレミアム会員 | | 3 | 法人会員 | **よく使う条件:** - プレミアム会員: `user_type = 2` - 個人会員(一般+プレミアム): `user_type IN (1, 2)`
今回は正しいクエリが生成されました。
-- 生成されたクエリ SELECT p.category_name, COUNT(DISTINCT o.order_id) AS order_count, SUM(oi.quantity) AS total_quantity, SUM(oi.quantity * oi.price) AS total_sales FROM `demo-project.demo_ec_sales.orders` o INNER JOIN `demo-project.demo_ec_sales.order_items` oi ON o.order_id = oi.order_id INNER JOIN `demo-project.demo_ec_sales.products` p ON oi.product_id = p.product_id INNER JOIN `demo-project.demo_ec_sales.users` u ON o.user_id = u.user_id WHERE o.order_status = 4 AND u.user_type = 2 AND o.order_date >= '2025-11-01' AND o.order_date < '2025-12-01' GROUP BY p.category_name ORDER BY total_sales DESC

検証 4: マーケティングデータセットを追加する
次に、マーケティング用スキルを追加して別ドメインの分析を試しました。
終了済みの Google 広告キャンペーンの ROAS をキャンペーン別に計算してください
今回は、適切にLEFT JOINを判断できていたり、終了のステータス(3)で正しくフィルタできています。
-- 生成されたクエリ SELECT c.campaign_name, c.channel, COUNT(DISTINCT i.impression_id) as impressions, COUNT(DISTINCT cl.click_id) as clicks, COUNT(DISTINCT cv.conversion_id) as conversions, SUM(i.cost) as total_cost, SUM(cv.revenue) as total_revenue, ROUND(SUM(cv.revenue) / NULLIF(SUM(i.cost), 0), 2) as roas FROM `demo-project.demo_marketing.campaigns` c LEFT JOIN `demo-project.demo_marketing.ad_impressions` i ON c.campaign_id = i.campaign_id LEFT JOIN `demo-project.demo_marketing.ad_clicks` cl ON i.impression_id = cl.impression_id LEFT JOIN `demo-project.demo_marketing.conversions` cv ON cl.click_id = cv.click_id WHERE c.status = 3 -- 終了済み AND c.channel = 'google_ads' -- Google 広告のみ GROUP BY 1, 2 ORDER BY roas DESC
また、EC 側のスキルはロードされませんでした。Progressive Disclosure が期待通りに機能しています。

検証 5: 複数ドメインをまたぐ分析
EC とマーケティング両方のデータが必要なケースを試しました。
キャンペーンデータと売上データを見比べて、キャンペーン以外からの収益を集計してください
この依頼では、全てのスキルがロードされ、両方のデータセットを結合した正しいクエリが生成されました。
--- 生成されたクエリ WITH campaign_orders AS ( SELECT DISTINCT order_id FROM `demo-project.demo_marketing.conversions` WHERE order_id IS NOT NULL ) SELECT o.order_id, o.order_date, SUM(oi.quantity * oi.price) as order_amount FROM `demo-project.demo_ec_sales.orders` o INNER JOIN `demo-project.demo_ec_sales.order_items` oi ON o.order_id = oi.order_id LEFT JOIN campaign_orders co ON o.order_id = co.order_id WHERE o.order_status != 9 -- キャンセル除外 AND co.order_id IS NULL -- キャンペーン経由ではない注文のみ GROUP BY o.order_id, o.order_date ORDER BY o.order_date DESC, o.order_id LIMIT 20

検証 6: グラフによる可視化
分析の場合、可視化まで行いたいことが多いのではないでしょうか。 グラフ描画に関するskillを設定していない場合、リッチなダッシュボードを生成する傾向があります。

artifact-charts スキルはシンプルなチャートを生成するスキルになっており、Chart.js のテンプレートにデータを差し込むだけで即座にグラフを描画できます。
--- name: artifact-charts description: "データ分析結果を高速にグラフ化。アーティファクトで棒グラフ、折れ線グラフ、円グラフを即座に描画。可視化、グラフ作成、チャート描画時に使用。" --- # 高速グラフ描画 データを受け取ったら、以下のテンプレートにデータを差し込んでアーティファクトを生成する。 ## ポリシー: シンプルさを最優先 - **1 リクエスト = 1〜2 グラフ**: ダッシュボードは作らない - **装飾は最小限**: アニメーション、グラデーション、影は使わない - **凡例・ラベルは必要な場合のみ**: データが自明なら省略 - **色は単色 or 3 色まで**: 視認性を優先 - **インタラクティブ機能は不要**: ホバー、ズーム、フィルタは追加しない **禁止事項:** - 複数グラフを並べたダッシュボード - タブ切り替え UI - リアルタイム更新機能 - 外部データ読み込み ## グラフ選択 | データの性質 | グラフ | 例 | |-------------|--------|-----| | カテゴリ比較 | 棒グラフ | カテゴリ別売上 | | 時系列推移 | 折れ線 | 月別推移 | | 構成比 | 円グラフ | 売上構成比 | ...(以降省略)

まとめ
Claude Skills を活用することで、BigQuery MCP 単体では実現できなかったドメイン知識の注入が可能となり、実用的なデータ分析を短時間で実行できることが確認できました。 また、グラフ描画まで一気通貫で実行してくれるので、レポーティング資料の作成まで自動化することも可能ですね。 クイックに AI での分析環境を立ち上げる際には選択肢の一つになるのではないでしょうか。