お問い合わせ

技術・ツール紹介

BigQueryのAI.AGG関数の使い方|解約理由や問い合わせの自由記述をSQLで要約・集計する

佐藤 恒株式会社INVOX 代表取締役 CEO

Google Cloudは2026年10月13日、BigQueryのAI.AGG関数を一般提供(GA)にしました(BigQueryのリリースノート(別タブで開く))。

AI.AGGは、複数の行のテキストや画像を、自然言語の指示に沿って1つの答えにまとめる集計関数です。SUMやCOUNTのように、GROUP BYと組み合わせて使えます。

解約時のアンケートの自由記述や、問い合わせの本文、商談のメモなどを全体として把握するには、これまで1件ずつ読むか、1行ずつAIで処理した結果をさらにまとめる必要がありました。AI.AGGを使うと、複数の行をまとめた要約を、BigQueryの中でSQLだけで出せます。

本記事では、AI.AGGの構文と必要な権限を公式のドキュメントで整理したうえで、解約時のコメントのデモ用のデータで試した結果と、注意点を紹介します。

AI.AGG関数とは

AI.AGGは、BigQueryの生成AIの関数の1つです。指定した列の値を、Vertex AIのGeminiのモデルに渡し、指示(プロンプト)に沿ってまとめた結果を返します。

以下は2026年10月時点の情報です。

できること

公式のドキュメントとブログでは、次のような使い方が紹介されています(AI.AGG関数のリファレンス(別タブで開く)、How BigQuery’s AI.AGG() works(別タブで開く))。

  • グループごとの要約:映画ごとのレビュー、投稿者ごとの投稿などを、GROUP BYで分けて要約する
  • 分類の洗い出し:商品の名前と説明から、どんな種類の商品があるかを挙げる
  • ログの分析:大量のログから、遅延や再試行の繰り返しなどの傾向を見つける
  • 画像の要約:Cloud Storageの画像を読み、何が写っているかをまとめる

入力には、テキストのほか、画像・動画・音声・PDFも使えます。

大量の行をまとめる仕組み

行が多いと、1回でモデルに渡せる量(コンテキストウィンドウ)を超えます。AI.AGGは、行を自動で小分けにして要約し、その要約をさらにまとめる、という段階的な集計をします。利用者がデータの量を気にして分割する必要はありません。

構文

AI.AGG(
  [DISTINCT] 入力,
  指示
  [, connection_id => '接続']
  [, endpoint => 'モデル']
  [, max_error_ratio => 許容するエラーの割合]
  [, output_schema => '出力の形']
)
  • 入力:STRING、または複数の列をまとめたSTRUCT
  • 指示:どうまとめるかを自然言語で書く
  • endpoint:使うGeminiのモデル。省略するとBigQueryが選ぶ
  • output_schema:出力の形を指定すると、STRINGではなく構造化された値(STRUCT)が返る

出力は、グループごとに最大1万トークンです。グループの数は1,000以下が推奨されています。

必要な権限

接続(connection_id)を指定しない場合は、クエリを実行した人の権限(エンドユーザーの認証情報)でVertex AIを呼び出します。公式のドキュメントでは、使う人に次の2つのロールを付与する手順が案内されています(生成AIの関数の権限の設定(別タブで開く))。

  • roles/aiplatform.user(以前の名称はVertex AIユーザー。2026年10月時点のドキュメントではGemini Enterprise Agent Platform Userと表記)
  • BigQueryジョブユーザー(roles/bigquery.jobUser)

48時間以上かかるクエリの場合は、接続(サービスアカウント)を使います。

解約時のコメントで試してみた

ここからは、2026年10月14日に試した結果を紹介します。

データは、架空の動画学習のサブスクリプションサービス「Lumina」の、解約時のコメントを想定したデモ用のデータです。Lite・Standard・Premiumの3つのプランの顧客の、40件の自由記述を用意しました。

テーブルは作らず、クエリの中にデータを書いて実行しています。モデルは指定せず、既定のものを使いました。

プランごとに要約する

まず、プランごとにGROUP BYで分けて、解約の理由を要約しました。

SELECT
  plan,
  COUNT(*) AS n,
  AI.AGG(
    comment,
    '動画学習サービスの解約時のコメントです。解約の理由を多い順に3つまで、それぞれ1文で日本語でまとめてください。最後に、このプランの顧客に効きそうな対策を1文で書いてください。'
  ) AS summary
FROM cancel_comments
GROUP BY plan
ORDER BY plan

AI.AGGでプランごとに解約理由を要約したクエリの結果。Liteは学習時間の確保、価格の割高感、オフライン再生や検索性などの機能面。Standardは学習時間の確保、中・上級者向けの講座の不足、価格と他社への乗り換え。Premiumは上級者向けの講座の不足、法人利用に適した機能がないこと、講師への質問の回答の遅さ。それぞれに対策の1文がついている

AI.AGGでプランごとに要約した結果(デモ用のデータ)

すぐに、プランごとに3つの理由と対策が返ってきました。

Premiumでは「複数人での利用や法人決済、領収書の対応」が2番目の理由に挙がっています。選択肢のアンケートには出てこない、上位プランならではの理由です。自由記述をプランごとに読み比べる手間を、SQL 1本で省けます。

分類と件数を出してみる

次に、output_schemaで出力の形を指定し、理由の分類と件数、代表的なコメントを出しました。

SELECT
  AI.AGG(
    comment,
    '動画学習サービスの解約時のコメントです。解約の理由を分類し、分類ごとの件数と、代表的なコメントを1つ挙げてください。件数の多い順に並べてください。',
    output_schema => 'topics ARRAY<STRUCT<name STRING NOT NULL, count INT64 NOT NULL, example STRING NOT NULL>>'
  ) AS result
FROM cancel_comments

7つの分類と件数が、配列として返ってきました。件数の合計は40で、入力の件数と一致します。

件数は、1件ずつ分類して数える

ただし、AI.AGGが返した件数は、モデルが全体を読んで出した推定です。確かめるために、AI.AGGが出した分類をもとに7つの分類を決め、AI.CLASSIFYで1件ずつ分類してから、COUNTで数えました。

WITH classified AS (
  SELECT
    plan,
    AI.CLASSIFY(comment, ['学習時間の確保が難しい', 'コンテンツの不足', '決済の失敗', '目的を達成した', '価格・他社との比較', '機能・使い勝手', '法人利用・請求']) AS category
  FROM cancel_comments
)
SELECT category, COUNT(*) AS n,
  COUNTIF(plan = 'Lite') AS lite, COUNTIF(plan = 'Standard') AS standard, COUNTIF(plan = 'Premium') AS premium
FROM classified
GROUP BY category
ORDER BY n DESC

AI.AGGの出力とAI.CLASSIFYで数えた件数の比較。AI.AGGでは決済・システムトラブルが7件、AI.CLASSIFYで1件ずつ分類すると決済の失敗は5件。AI.CLASSIFYの結果では、コンテンツの不足9件、学習時間の確保が難しい8件、機能・使い勝手6件、価格・他社との比較5件、決済の失敗5件、法人利用・請求4件、目的を達成した3件で、プラン別の件数も出ている

AI.AGGの推定と、AI.CLASSIFYで数えた件数の比較(デモ用のデータ)

AI.AGGでは「決済・システムトラブル」が7件でしたが、1件ずつ分類すると「決済の失敗」は5件でした。デモ用のデータを書いたときの想定とも、AI.CLASSIFYの5件が一致しています。

また、プランごとの要約では、決済の失敗はどのプランでも上位3つに入りませんでした。全体の13%(40件中5件)あり、本人が解約を望んでいない可能性が高い、見逃したくない理由です。要約では、件数の少ない理由が埋もれることがあります。

このことから、次のように使い分けるのがおすすめです。

やりたいこと 使う関数
どんな理由や話題があるかを洗い出す AI.AGG
グループごとの傾向を、文章で読む AI.AGG + GROUP BY
理由ごとの件数や割合を出す AI.CLASSIFY + COUNT

公式のブログでも、AI.AGGで分類を洗い出し、その分類をAI.CLASSIFYに渡して1件ずつ分類する流れが紹介されています。

AI.AGGを使うときの注意点

費用は、Vertex AIのGeminiの利用料がかかる

AI.AGGは、BigQueryのクエリの料金とは別に、Vertex AIのGeminiの利用料がかかります。段階的に集計する仕組みのため、モデルに送られるトークンは、元のデータの量より多くなります。

公式のドキュメントでは、AI.COUNT_TOKENS関数で入力のトークン数を見積もることや、先にWHEREやLIMITでデータを絞ることが勧められています。JOINやORDER BY … LIMITを含むクエリでは、思ったより多くの行が処理されることがあるため、結果をいったんテーブルに保存してから使うことも勧められています。

NULLを含む行は飛ばされる

入力にNULLがある行は、集計から外されます。複数の列をSTRUCTで渡す場合は、1つの列がNULLなだけでその行全体が外れます。IFNULLで空欄を埋めてから渡します。

結果は実行のたびに変わる

生成AIの出力のため、同じクエリでも、実行するたびに文章が少し変わります。定期的なレポートに使う場合は、結果をテーブルに保存しておきます。

個人情報を含むテキストに注意する

問い合わせや商談のメモには、氏名や連絡先が含まれることがあります。社内のルールに沿って、Vertex AIに渡してよいデータかを確かめ、必要な列だけを渡します。

Claudeと組み合わせて使う

ClaudeからBigQueryに接続していれば、AI.AGGを使ったクエリの作成や実行も、日本語で依頼できます。接続の手順は、「ClaudeとBigQueryを連携する方法(別タブで開く)」で解説しています。

プロンプト例
cancel_comments テーブルの comment 列を、plan ごとに AI.AGG で要約してください。解約の理由を多い順に3つと、対策を1文で出してください。実行する前に、AI.COUNT_TOKENS で入力のトークン数を見積もってください。

プロンプト例
AI.AGG で解約の理由の分類を洗い出し、その分類で AI.CLASSIFY を使って1件ずつ分類してください。分類ごと・プランごとの件数を表にしてください。

選択肢で集めた解約理由の分析の仕方は、「解約理由の分析のやり方(別タブで開く)」で解説しています。自由記述をAI.AGGで要約し、選択肢の集計と並べて読むと、選択肢には出てこない理由に気づけます。

まとめ

AI.AGGは、自由記述や画像などを、自然言語の指示に沿ってSQLの中で要約できる集計関数です。2026年10月13日に一般提供になりました。

  • 使いどころ:グループごとの要約、理由や話題の洗い出し
  • 件数を出すとき:AI.AGGの件数は推定。AI.CLASSIFYで1件ずつ分類してからCOUNTで数える
  • 注意点:Vertex AIの利用料がかかる。NULLの行は外れる。結果は実行のたびに変わる

解約時のコメントや問い合わせなど、読まれずに溜まっているテキストがBigQueryにある場合は、まず少ない件数で試し、要約の質と費用を確かめてから広げていくのがおすすめです。

CONTACT

「事業成長に繋がるデータ活用」ならINVOXへ

相談する

何から手を付ければいいか分からない段階でも構いません。現状を伺い、次にやるべきことをお伝えします。

お問い合わせ

資料ダウンロード

サービスごとに、提供内容・支援実績・進め方と費用の目安をまとめています。社内での検討や共有にお使いください。

資料ダウンロード