GA4 の BigQuery エクスポートで自分で SQL を書き始めたものの、正しいかを見てくれる人がいない方向けの記事です。AI に SQL をレビューさせるプロンプトを 4 種類試し、指摘が本当に正しいかを実行して確かめた結果と、そのまま使えるプロンプトの原文を紹介します。
この記事で分かること
- わざと誤りを 1 つずつ入れた 5 本の SQL を、AI がどこまで見つけて直せたか(4 種類のプロンプトで計 20 回)
- 「定義を先に渡す」と、キー名の打ち間違いのような見落としやすい誤りも見つかったこと
- 指摘を「指摘箇所・修正前・修正後・理由」の 4 列表で受け取ると、余計な指摘が減り、「修正後」の列をそのまま元の SQL に当てて実行できたこと
ざっくり言うと:形式を決めて頼むと、修正をそのまま当てて確かめられた
筆者が 2026-11-06 に試した結果を先にまとめます。誤りは全部で 5 つ、プロンプトは 4 種類なので、組み合わせは 20 通りです。
| プロンプト | 見つけた誤り | 直せた誤り | 余計な指摘 |
|---|---|---|---|
| 1. 自由指摘 | 4 / 5 | 4 | 16 |
| 2. 4 列表 | 4 / 5 | 4 | 0 |
| 3. 定義+4 列表 | 5 / 5 | 5 | 1 |
| 4. 修正版 SQL を返す | 4 / 5 | 4 | 3 |
数字はすべて、筆者が AI の答えを 1 件ずつ分類し、修正版の SQL を BigQuery で実行して数えたものです。見つけた 17 件は、直すべき列がすべて正解の SQL と同じ値になりました(ただし 1 件だけ、元と同じ列名のまま中身の定義を変えた列が含まれていました)。
ただし、キー名の打ち間違いは、定義を渡さなかった 3 つのプロンプトがそろって見逃しました。2 つのプロンプトは、間違ったキー名を「正しい」と説明しています。AI の「問題なし」は、実行して確かめるまで信じないのが安全です。
使うデータと、誤りを入れた 5 本の SQL
データ:GA4 の公開サンプル(3 日分)
使ったのは、Google が BigQuery の一般公開データセットとして出している ga4_obfuscated_sample_ecommerce です。Google Merchandise Store(Google の公式グッズのネットショップ)の GA4 データを難読化(個人を特定できないように値を加工すること)したもので、2020-11-01〜2021-01-31 の 3 か月分が入っています(Google for Developers)。
GA4 の BigQuery エクスポートでは、events_20210131 のように 1 日 1 つのテーブルが作られます(Google アナリティクス ヘルプ)。今回は 2021-01-29〜2021-01-31 の 3 日分だけを読みました。
1 本の SQL が読むデータは最大でも約 22.5 MB でした(dry run(実際には実行せず、読むデータ量だけを見積もる機能)で確認)。BigQuery のオンデマンド料金(読んだデータ量に応じて払う料金体系)は毎月 1 TiB まで無料なので、無料枠の 0.002% 程度です(Google Cloud の料金ページ)。
わざと入れた 5 つの誤り
1 本の SQL に誤りを 1 つだけ入れました。どの SQL も、冒頭に「目的」をコメントで書いています。
| 番号 | 誤り | 誤りの書き方 | 正しい書き方 | 誤りの SQL の結果 |
|---|---|---|---|---|
| 誤り 1 | 期間の端のずれ | BETWEEN '20210129' AND '20210130' | 終わりを '20210131' に | 1/31 の行が無い(2 行だけ) |
| 誤り 2 | 売上の単位の思い込み | purchase_revenue_in_usd / 1000000 | 割らない | 売上が 3 日とも 0.0 |
| 誤り 3 | キー名の打ち間違い | key = 'engagement_time_ms' | 'engagement_time_msec' | 時間が 3 日とも NULL(値が入っていないことを表す特別な値) |
| 誤り 4 | ユーザーを user_id で数える | COUNT(DISTINCT user_id) | user_pseudo_id で数える | ユーザー数が 3 日とも 0 |
| 誤り 5 | 購入の絞り込みを集計の前に掛ける | WHERE ... AND event_name = 'purchase' | WHERE から外す | 購入セッションの割合が 100% |
それぞれの誤りの根拠は次のとおりです。
- 誤り 2:
ecommerce.purchase_revenue_in_usdは、最初から米ドルの標準単位で入っています(スキーマの説明)。micros(100 万分の 1 単位)だと思い込んで割ると、190 ドルが 0.00019 になり、小数 2 桁で丸めると 0 になります。この誤りの SQL には-- micros をドルに換算というコメントも付けました。コメントが書き手の思い込みを表している、という実際によくある形にしたためです。AI にとっては、このコメントが手がかりになった可能性があります。 - 誤り 3:
event_params(イベントに付くパラメータを、キーと値の組で持つ列)に無いキー名を指定すると、取り出した値は NULL になります。BigQuery の SUM は NULL 以外の値だけを足し、足す値が 1 つも無いときは NULL を返すので(集計関数の説明)、エラーにならずに NULL が返ります。 - 誤り 4:
user_idは、サイト側でログイン ID などを送った場合に入る列です。user_pseudo_idは GA4 がブラウザや端末ごとに付ける仮名の ID で、公式のサンプルクエリもこちらで数えています(Google for Developers)。今回のサンプルでは、user_idで数えると 3 日とも 0 でした。 - 誤り 5:WHERE は集計の前に行を絞り込みます。購入イベントだけを残すと、分母のセッションも購入があったセッションだけになります。条件を集計の中に置く書き方(COUNTIF など)とは結果が変わります(集計関数の説明)。
セッション数を session_start の件数で数える誤りや、UNNEST(繰り返しの列を行に展開する関数)を JOIN(表と表をつなぐ書き方)で書いて行が増える誤りは、前回の記事「AI に書かせた GA4 の BigQuery SQL を検算する」で扱ったので、今回は入れていません。
AI に渡した SQL は、5 本とも次のとおりです。誤り 1〜4 は短い SQL で、誤り 5 だけセッションを数えるため長くなっています。
誤り 1(期間の端のずれ):
-- 目的: 2021-01-29〜2021-01-31 の 3 日間の、日別のユーザー数とイベント数
SELECT
event_date,
COUNT(DISTINCT user_pseudo_id) AS users,
COUNT(*) AS events
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20210129' AND '20210130'
GROUP BY event_date
ORDER BY event_date
誤り 2(売上の単位の思い込み):
-- 目的: 2021-01-29〜2021-01-31 の 3 日間の、日別の購入売上(米ドル)
SELECT
event_date,
COUNT(*) AS purchases,
ROUND(SUM(ecommerce.purchase_revenue_in_usd) / 1000000, 2) AS revenue_usd -- micros をドルに換算
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20210129' AND '20210131'
AND event_name = 'purchase'
GROUP BY event_date
ORDER BY event_date
誤り 3(キー名の打ち間違い):
-- 目的: 2021-01-29〜2021-01-31 の 3 日間の、日別のエンゲージメント時間の合計(分)
SELECT
event_date,
ROUND(SUM((SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'engagement_time_ms')) / 60000, 1) AS engagement_minutes
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20210129' AND '20210131'
GROUP BY event_date
ORDER BY event_date
誤り 4(ユーザーを user_id で数える):
-- 目的: 2021-01-29〜2021-01-31 の 3 日間の、日別のユーザー数
SELECT
event_date,
COUNT(DISTINCT user_id) AS users
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20210129' AND '20210131'
GROUP BY event_date
ORDER BY event_date
誤り 5(購入の絞り込みを集計の前に掛ける)。AI に渡したときは、最後の「← わざと入れた誤り」というコメントは付けていません:
-- 目的: 2021-01-29〜2021-01-31 の 3 日間の、日別の全セッション数・購入があったセッション数・購入セッションの割合(%)
-- セッションは user_pseudo_id と ga_session_id の組で数える
SELECT
event_date,
COUNT(DISTINCT CONCAT(user_pseudo_id, CAST((SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS STRING))) AS sessions,
COUNT(DISTINCT IF(event_name = 'purchase', CONCAT(user_pseudo_id, CAST((SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS STRING)), NULL)) AS purchase_sessions,
ROUND(100 * SAFE_DIVIDE(
COUNT(DISTINCT IF(event_name = 'purchase', CONCAT(user_pseudo_id, CAST((SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS STRING)), NULL)),
COUNT(DISTINCT CONCAT(user_pseudo_id, CAST((SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS STRING)))), 2) AS purchase_session_rate
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20210129' AND '20210131'
AND event_name = 'purchase' -- ← わざと入れた誤り
GROUP BY event_date
ORDER BY event_date
レビュープロンプト 4 本(原文)
4 本とも、プロンプトの最後に、誤りを入れた SQL を 1 本、sql のコードブロックで囲んで貼って送りました。AI には「誤りが 1 つある」とは伝えていません。実際のレビューでは、誤りがいくつあるか分からないからです。
プロンプト 1:自由指摘
次の BigQuery の SQL をレビューして、問題があれば指摘してください。対象は GA4 の BigQuery エクスポートの公開サンプル(bigquery-public-data.ga4_obfuscated_sample_ecommerce)です。
プロンプト 2:4 列表で返させる
次の BigQuery の SQL をレビューしてください。対象は GA4 の BigQuery エクスポートの公開サンプル(bigquery-public-data.ga4_obfuscated_sample_ecommerce)です。
指摘は「指摘箇所・修正前・修正後・理由」の 4 列の Markdown の表で返してください。修正前と修正後には、SQL の該当部分をそのまま書いてください。表の外に説明は書かないでください。問題がなければ「指摘なし」とだけ書いてください。
プロンプト 3:定義を渡してから 4 列表で返させる
次の BigQuery の SQL をレビューしてください。対象は GA4 の BigQuery エクスポートの公開サンプル(bigquery-public-data.ga4_obfuscated_sample_ecommerce)です。
この集計では、次の定義を使います。
- 期間: SQL の冒頭のコメントに書いた日付の範囲。テーブルは日次の events_YYYYMMDD で、_TABLE_SUFFIX は YYYYMMDD の文字列
- ユーザー数: COUNT(DISTINCT user_pseudo_id)
- セッション: user_pseudo_id と、event_params の ga_session_id(int_value)の組
- 売上: ecommerce.purchase_revenue_in_usd。米ドルの標準単位で入っている
- エンゲージメント時間: event_params の engagement_time_msec(int_value、ミリ秒)
- event_params は key(STRING)と value(string_value・int_value・double_value など)を持つ繰り返しの列
この定義と SQL の冒頭のコメント(目的)に照らして、指摘を「指摘箇所・修正前・修正後・理由」の 4 列の Markdown の表で返してください。修正前と修正後には、SQL の該当部分をそのまま書いてください。表の外に説明は書かないでください。問題がなければ「指摘なし」とだけ書いてください。
プロンプト 4:修正版の SQL を返させる
次の BigQuery の SQL をレビューし、問題を直した修正版の SQL 全体を 1 つの sql コードブロックで返してください。直した点は、コードブロックの後に箇条書きで短く書いてください。直す必要がなければ、元の SQL をそのまま返してください。対象は GA4 の BigQuery エクスポートの公開サンプル(bigquery-public-data.ga4_obfuscated_sample_ecommerce)です。
AI には Claude(モデル名 claude-sonnet-5-5)を使い、Claude Code のコマンド(claude -p)から実行しました。20 回はそれぞれ別の会話で、前の答えを見ていません。筆者の Claude Code の回答スタイルの設定が効いた状態で実行したため、自由形式の答えには補足や「次の一手」が付いています。
AI の指摘と修正版:4 列表で受け取る
4 列表の形は、筆者がこのサイトの運用で、AI に記事の文章を直させたときに使った形です。そのときは「当てたか・直す前・直した後・理由」の表で受け取り、20 件の修正を当て、当てなかった修正は 0 件でした。直す前と後がそのまま並ぶので、元の文に本当にその文字があるかと、当てた後どうなるかをすぐ確かめられます。
図 1 のとおり、検算でいちばん使うのは「修正後」の列です。たとえば誤り 5 に対するプロンプト 2 の答えは、次の 1 行だけでした(理由は筆者が要約)。
| 指摘箇所 | 修正前 | 修正後 | 理由(要約) |
|---|---|---|---|
| WHERE 句の event_name 条件 | AND event_name = 'purchase' を含む WHERE | _TABLE_SUFFIX の条件だけの WHERE | 分母のセッションも購入セッションだけになり、割合が 100% になる |
検算:修正版 SQL と正解 SQL を実行して結果を並べる
AI の修正版(4 列表なら「修正後」を元の SQL に当てたもの)を BigQuery で実行し、筆者が書いた正解の SQL の結果と並べました。代表として、誤り 5 の 3 日分を示します。
| 日付 | 誤りの SQL(セッション・購入・割合) | 正解の SQL | AI の修正版(4 本とも) |
|---|---|---|---|
| 2021-01-29 | 51・51・100.0% | 3,799・51・1.34% | 3,799・51・1.34% |
| 2021-01-30 | 28・28・100.0% | 2,908・28・0.96% | 2,908・28・0.96% |
| 2021-01-31 | 18・18・100.0% | 2,849・18・0.63% | 2,849・18・0.63% |
割合は手計算でも確かめました。51 ÷ 3,799 = 1.34%、28 ÷ 2,908 = 0.96%、18 ÷ 2,849 = 0.63% で、BigQuery の結果と一致します。プロンプト 3 は区切り文字を足す提案も一緒に出しましたが、当てて実行しても値は変わりませんでした。
誤り 5 以外も含め、見つけた 17 件の修正版は、直すべき列がすべて正解と同じ値になりました。たとえば誤り 4 は、3 日とも 0 だったユーザー数が 3,386・2,610・2,546 になりました。
正解と列の形が合わなかったのは 1 か所だけです。プロンプト 1 は誤り 2 の修正版で、購入イベントの数を purchase_events という名前で残し(54・31・19)、元と同じ purchases という名前の列に、注文番号の重複を除いた数(7・6・1)を入れました。売上は正解と同じ 190.0・159.0・0.0 でした。AI はこの変更の理由を、同じ注文番号(transaction_id)の購入イベントが複数回送られると二重に数えるためだと説明していました。
購入イベントの数と注文数が 54 と 7 のように大きくずれているのは、このサンプルの性質かもしれません。AI の注意そのものは的外れではありません。ただ、元と同じ列名で中身の定義が変わるので、列名だけを見て正解と並べると「購入件数が違う」と見誤ります。
なお、1/31 は購入イベントが 19 件あるのに売上が 0.0 でした。正解の SQL でも同じ値なので、比較には影響しません。このサンプルは難読化のため内部の整合性が少し崩れることがあると公式に書かれており(Google for Developers)、その影響と考えられます。
図 2 が今回の検算の手順です。AI の答えを読むだけで終わらせず、必ず「実行して比べる」段階を通します。
プロンプト × 誤りの一覧表:見つけた・直せた・余計な指摘
20 通りの結果をまとめたのが図 3 です。○ は見つけて直せたこと、× は見逃したことを表します。
| プロンプト | 期間の端 | 売上の単位 | キー名 | user_id | WHERE の絞り込み |
|---|---|---|---|---|---|
| 1. 自由指摘 | ○ | ○(注) | × | ○ | ○ |
| 2. 4 列表 | ○ | ○ | ×(指摘なし) | ○ | ○ |
| 3. 定義+4 列表 | ○ | ○ | ○ | ○ | ○ |
| 4. 修正版 SQL | ○ | ○ | ×(元のまま返した) | ○ | ○ |
注:売上の列は正解と一致しましたが、purchases という同じ列名に、注文番号の重複を除いた数という別の定義の値が入りました(検算の節を参照)。○ は「わざと入れた誤りに関わる列が、正解と同じ値になった」ことを表します。
図 4 のとおり、見つけた数はプロンプトでほとんど変わりませんでした。大きく違ったのは余計な指摘の数です。余計な指摘とは、わざと入れた誤り以外に AI が挙げた問題や改善案のことで、筆者が答えを読んで数えました。
| プロンプト | 余計な指摘の中身(例) |
|---|---|
| 1. 自由指摘(16 件) | 日付を DATE 型(日付専用のデータの種類)に変える、式を WITH 句(途中の計算結果に名前を付けて使い回す書き方)にまとめる、当日分の速報テーブルが混ざる可能性、購入件数の数え方 |
| 2. 4 列表(0 件) | なし |
| 3. 定義+4 列表(1 件) | セッションの組を作るときに区切り文字を入れる |
| 4. 修正版 SQL(3 件) | 式を WITH 句にまとめる、日付を DATE 型に変える提案、購入件数の数え方の提案 |
プロンプトの選び方:定義を先に渡す効果と、修正版を返させるときの注意
定義を先に渡すと、「名前の誤り」まで見つかる
キー名の打ち間違い(誤り 3)を見つけたのは、定義を渡したプロンプト 3 だけでした。プロンプト 1 と 4 は、engagement_time_ms は整数なので int_value から読むのが正しい、という趣旨の説明をし、プロンプト 2 は「指摘なし」と答えました。
キー名が違っても SQL の文法としては正しいので、SQL だけを見ても誤りと判断する手がかりが少なかったと考えられます。定義に正しいキー名を書いておくと、「定義と食い違っている」という形で見つけられます。
ただし、今回のプロンプト 3 の定義には、誤り 2〜4 の答えがほぼ書かれています。5 / 5 という結果は「定義に書いたことと違う部分は見つかる」ことを示すもので、AI の力が上がったことを示すものではありません。自分の SQL で使うときも、使っている列とキー名を定義に書き出しておくのが効果的だと考えられます。
修正版 SQL を返させるときは、余計な書き換えに注意する
修正版 SQL を返させると、答えをそのまま実行できます。一方で、頼んでいない書き換えが混ざると、どこが直されたのかを差分(修正前と修正後で違う部分)で確かめる手間が増えます。
修正版は、全体を正解と比べるか、修正前と修正後の差分を見てから使います。
選び方の目安
| やりたいこと | 向いているプロンプト | 理由 |
|---|---|---|
| まず誤りだけを手短に知りたい | 2. 4 列表 | 余計な指摘が 0 件で、当てる場所がすぐ分かった |
| 見落としを減らしたい | 3. 定義+4 列表 | 定義と食い違う名前や単位まで見つけた |
| 書き方の改善も知りたい | 1. 自由指摘 | 改善のヒントは多いが、本題を探す手間が増える |
| すぐ実行して比べたい | 4. 修正版 SQL | 実行は速いが、頼んでいない書き換えを確かめる必要がある |
つまずきやすい点
AI が「正しい SQL」を別の定義で直す
AI の修正版は、元と同じ列名のまま、中身の定義を変えることがあります。今回は、元の購入イベントの数を purchase_events という別の名前で残し、purchases という同じ名前の列に注文番号の重複を除いた数を入れました。そのため、purchases の値が 54 から 7 に変わって見えました。AI は理由を書いていたので、答えの説明と列名を読み、直していない列も含めて正解と並べると気づけます。
指摘が多すぎて読めない
自由指摘では、5 本で合計 16 件の余計な指摘が付き、本題が埋もれました。4 列表で返させ、「表の外に説明は書かない」と頼むと、今回は 0 件になりました。
「問題なし」をそのまま信じる
キー名の打ち間違いは、AI が「正しい」と説明しても、実行すれば NULL が返るので気づけます。AI のレビューは、実行して確かめる作業の代わりにはなりません。
1 回の結果を一般化しない
今回は、モデル 1 種類で、各プロンプトを 1 回ずつ実行しました。誤りは 1 本に 1 つだけで、判定したのは筆者 1 人です。同じプロンプトでも、モデルや実行のたびに答えは変わりうるので、この割合を一般的な性能として扱わないでください。
余計な指摘の数(自由指摘の 16 件、4 列表の 0 件)も、筆者の Claude Code の回答スタイルの設定と、プロンプト 2 の「表の外に説明は書かない」という指示の影響を受けている可能性があります。0 件になった理由が表の形なのか、この一文なのかは、今回の実験では分けられません。回答スタイルの設定が無い環境では、件数が変わりうると考えてください。
まとめ
- AI は 20 通り中 17 通りで誤りを見つけ、見つけた分は直すべき列の値が正解と一致しました。ただし、キー名の打ち間違いは定義を渡したときだけ見つかりました
- 指摘を「指摘箇所・修正前・修正後・理由」の 4 列表で受け取ると、余計な指摘が減り、修正後をそのまま当てて検算できました
- AI の「問題なし」や修正版は、正解の SQL か手計算と並べて実行してから使いましょう
次にやること
検算した数字をどう見せるかの参考には、ダッシュボードの一覧で、このサイトが公開データから作ったダッシュボードの例をご覧ください。自分で書いた SQL や AI に直させた SQL が定義どおりか、第三者の目で確かめたい場合は、BigQuery SQL レビューパックもご利用いただけます。
参考にした一次情報
- Google for Developers:GA4 の e コマースのサンプルデータセット
- Google アナリティクス ヘルプ:BigQuery Export のスキーマ
- Google Cloud:BigQuery の集計関数
- Google Cloud:BigQuery の料金
更新履歴
- 2026-11-09: 定期点検で、本文の18か所を直しました。