GA4 UNNEST処理の解説

BigQueryにエクスポートされたGA4のデータを取り扱う際にぶつかる大きな壁が「UNNEST(アンネスト)処理」となる。つまり、テーブル構造が1行1行の単純構成になっておらず、1行の中に入れ子になっているテーブル構成のため、入れ子になっているデータを単純にSELECT文で取り出そうとしてもエラーとなるため、UNNNEST処理が必要になる。

ネスト(入れ子)構造とは

例としてpage_viewイベントを例にどのようにUNNEST処理が必要になるのかを解説する。GA4のRawデータでは、1つのpage_viewイベントに対して、以下のようなデータ構成になっている。

  • event_name:page_view
  • event_params.key:
    ∟ page_location(URL): https://example.com/home
    ∟ page_title(タイトル): ホーム画面
    ∟ ga_session_id(セッションID): 123456789

これをBigQueryのGA4のテーブルをみると、1行のなかに複数のパラメータが縦に並んで入っているように見え、これがネストされた状態といえる。このネストされた、例えばpage_locationの値を取り出そうとしても、そのままでは取り出せず、UNNESTでフラットな表形式に直す必要がある。

UNNESTでフラット化して抽出

UNNESTでテーブルをフラット化するとは、つまり入れ子状態のデータ構成を、ネストされていない1行1行の構成に直すということをUNNESTという。例えば、event_params.keyのpage_titleやpage_locationを取り出したければ、そのままSELECT文で取得することはできないため、UNNEST処理を施す必要がある。

UNNEST処理のサンプルクエリ

page_titleとpage_locationの値を取得するクエリは以下の通り。

CREATE TEMP FUNCTION date_from() RETURNS STRING AS ('20260601');
CREATE TEMP FUNCTION date_to() RETURNS STRING AS ('20260601');

WITH
  tmp_01 AS (
    SELECT
      event_name,
      REGEXP_REPLACE((SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location'), r'\?.*$', '') AS page_location,
      (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_title') AS page_title
    FROM
      `<project>.<dataset>.events_*`
    WHERE 1 = 1
      AND _TABLE_SUFFIX BETWEEN date_from() AND date_to()
      AND event_name = 'page_view'
  )

SELECT
  *
FROM
  tmp_01

▼クエリ解説

REGEXP_REPLACE((SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location'), r'\?.*$', '') AS page_location
  1. 局所的なUNNESTの発生
    BigQueryは、手順1で決まった1つの page_view 行に紐づく event_params(配列の箱)の中身だけを、メモリ上の超ミニテーブルに一時的に縦展開(UNNEST)される。
  2. フィルタリングと抽出
    展開されたミニテーブルに対して、すぐ後ろの WHERE key = ‘page_location’ を実行し、合致する1行だけに絞り込む。
  3. 値を1つだけ返す(スカラ副問い合わせ)
    絞り込まれた行から value.string_value(例: https://sem-report.com/?p=123)を抽出する。
  4. 関数の適用
    外側にある REGEXP_REPLACE 関数が走り、URL末尾のクエリパラメータ(?p=123)をカットして、https://sem-report.com/ に整形する。

この値が、新設された page_location という列の「値」 として、page_view の右側に配置される。

UNNESTの構文

SELECT (SELECT … FROM UNNEST(…) WHERE key = ‘xxx’)

  1. 全体を囲む ( ) =「1つの値に変換」
    SELECT句のなかに、さらに SELECT を書く(副問い合わせをする)場合、必ず全体を ( ) で囲む必要がある。この括弧には、「中のクエリを実行して、最終的に『1つの値(文字列や数値など)』として外側に返す」という意味を持つ。
  2. FROM UNNEST(event_params) =「探索範囲は、この行の箱の中だけ」
    通常のクエリであれば FROM テーブル名 と書くが、ここでは FROM UNNEST(event_params) と記述。これは、「今処理している、まさにその1行に紐づいている event_params(配列の箱)の中身だけを、ミニテーブルとして展開して使う」という意味になる。他の行のデータは一切見に行かない。
  3. WHERE key = ‘page_location’ =「名札で狙い撃ち」
    UNNESTされて目の前に並んだパラメータの中から、key が page_location である行(名札がついているデータ)だけに絞り込む。
  4. SELECT value.string_value =「中身の抽出」
    絞り込まれたデータから、文字列が入っている value.string_value の中身(URLなど)を抽出。

この構文を使う上では、「戻ってくる結果は、絶対に1行・1列(=1つの値)でなければならない」というルールがあり、これをデータベース用語でスカラ値と呼ぶ。もし、この副問い合わせの結果が「2行以上」になってしまうと、エラーを出して処理がストップする。

であるが、GA4の仕様上、1つのイベント(1行)の中に、page_location や page_title という同じ名前の key は絶対に1つしか存在しないルールになっているため、WHERE key = ‘page_location’ で絞り込めば、結果は必ず1行(1つの値)になる。だからこそ、この構文がエラーになることはない。

関連記事

【GA4SQL】ページ単位の平均エンゲージメント時間

【GA4 SQL】セッション単位のページ遷移数をBigQueryから取得

【詳解】session_engaged パラメーター

おすすめ記事

最近の記事
おすすめ記事
  1. [GA4] 総ユーザー数とは

  2. [BigQuery] マルチステートメントクエリの一時テーブル

  3. Dataformとは? GA4・BigQueryとの連携方法を解説

  1. 【GA4 SQL】初回訪問から初回CVまでの日数をBigQueryから取得

  2. 【GA4 SQL】キーイベントを達成したセッション数をBigQueryから集計

  3. BigQueryのWITH句(CTE)とサブクエリの使い分け

PAGE TOP