GA4導入/運用支援サービスの詳細
CARTA ZEROはGA4個人認定資格を保有するアナリストが多数在籍。GA4導入や計測カスタマイズ、BigQueryやBIダッシュボードも活用したGA4運用コンサルティングの実施など、お客様のご事情に合わせたご支援が可能です。
https://analytics.cartazero.co.jp/ga4
こんにちは。CARTA ZEROのアナリティクス担当の鉄羅陀です。
前回の記事【BigQuery】ARRAY,UNNESTって一体なに?では
の2点を説明し、実際にARRAY型のカラムをUNNEST演算子で行に展開&フラット化する例を紹介しました。
今回の記事ではARRAY型と組み合わせて使用されることの多いデータ型、STRUCT型についてご紹介したいと思います。
今回の記事のポイントは以下2点です。
BigQuery公式ドキュメント:Struct_typeのSTRUCT型の定義を確認してみましょう。
定義:順序付けられたフィールドのコンテナで、各フィールドは型(必須)とフィールド名(オプション)を持つデータ構造
.....。定義だけ読んでもよくわからないので、もっとかみ砕いて表現すると
STRUCT型とは,異なるデータ型を持ったいろんなデータをまとめて保有することができるデータ構造です。
具体例として、アーティスト「YOASOBI」のメンバーである「Ayase」さんをSTRUCT型で表現してみました。
(題材はなんでもいいでのですが、本稿執筆中ちょうどYOASOBIの曲が流れてきたので💁)
STRUCT構造の例1
--アーティスト「YOASOBI」のメンバー「Ayase」さんをSTRUCT型で表現
SELECT
STRUCT(
'非公表' AS full_name
,'Composer' AS role
,31 AS age
) AS ayase
;
結果は以下です。
確かに「ayase」というSTRUCT型のカラムは、異なるデータ型(STRING型、INT64型)を持ったいろんなデータ(full_name, role, age)をまとめて保有できていることが確認できます。
ついでにこの例を通じて、STRUCT型の厳密な定義も読み解いてみましょう。
定義:順序付けられたフィールドのコンテナで、各フィールドは型(必須)とフィールド名(オプション)を持つデータ構造
コンテナ
「ayase」カラムそのものを指しています。
各フィールドは型(必須)とフィールド名(オプション)を持つ
各フィールドは以下のような型・フィールド名を持っています
フィールド名:full_name (STRING型)
フィールド名:role (STRING型)
フィールド名:age (INT64型)
「ayase」という人物を大きなコンテナと見立てて、その中に「ayase」を構成(=STRUCT)している小さなデータを次々入れていく。STRUCT型はそのようなデータ構造を持つイメージを持つとわかりやすいと思います。
STRUCT型内の個別のフィールド値を取り出すには、ドット演算子 (.) を使用します。
以下の記法で、STRUCT型内に存在するそれぞれのフィールドへアクセスできます。
STRUCT型のカラム名.フィールド名
例えば「ayase」からageを取得したければ、
--アーティスト「YOASOBI」のメンバー「Ayase」さんをSTRUCT型で表現
WITH struct_sample AS (
SELECT
STRUCT(
'非公表' AS full_name
,'Composer' AS role
,31 AS age
) AS ayase
)
--ayase内に存在するageフィールドへアクセスする
SELECT ayase.age FROM struct_sample
;
を実行します。結果は以下になります。
この合わせ技がなかなか強力で、理解するとSQL内でかなり柔軟なデータ構造を定義することが可能になります。
(※実際GA4データをBigQueryにエクスポートしたときに作成されるイベントテーブルでは、「events_params」フィールドなどでこの合わせ技が使用されています)
今度はアーティスト「YOASOBI」自体をSTRUCT型、そしてARRAY型も組み合わせてもっと柔軟に表現してみましょう。
STRUCT構造の例2
--アーティスト「YOASOBI」をSTRUCT型で表現したクエリ
SELECT
STRUCT(
--活動開始日(DATE型)
DATE('2019-10-01') AS debut_date,
--活動継続中か(BOOL型)
TRUE AS is_active,
-- メンバー情報(ARRAY<STRUCT>型)
[
--Ayaseの情報(STRUCT型)
STRUCT(
'Ayase' AS name
,'非公表' AS full_name
,'Composer' AS role
,31 AS age
),
--ikuraの情報(STRUCT型)
STRUCT(
'ikura' AS name
,'幾田りら' AS full_name
,'Vocalist' AS role
,25 AS age
)
] AS members,
-- 代表曲リスト(ARRAY<STRING>型)
['アイドル', '夜に駆ける', '群青'] AS hit_songs
) AS yoasobi
;
実際に上記クエリを実行した結果です。
うーん、一見するとわかりにくいですね。「yoasobi」というSTRUCT型のカラムがどうなっているのかを少しだけ丁寧に解説します。
- 「yoasobi」カラム(STRUCT型)は以下のフィールドを内部に持っています。
フィールド名:debut_date (DATE型)
フィールド名:is_active (BOOL型)
フィールド名:members (ARRAY型)
1番目の要素はAyaseの情報がはいったSTRUCT型のカラムです。以下のフィールドを内部に持っています
フィールド名:name (STRING型)
フィールド名:full_name (STRING型)
フィールド名:role (STRING型)
フィールド名:age (INT64型)
2番目の要素はikuraの情報がはいったSTRUCT型のカラムです。以下のフィールドを内部に持っています
フィールド名:name (STRING型)
フィールド名:full_name (STRING型)
フィールド名:role (STRING型)
フィールド名:age (INT64型)
フィールド名:hit_songs (ARRAY型)
ポイントは
フィールド名:members (ARRAY型)
です!
members自体はARRAY型のカラムですが、その中の要素がSTRUCT型になっています。
なんとなく「yoasobi」というSTRUCT型のカラムがどうなっているのかイメージできたのではないでしょうか...?
練習として、「yoasobi」カラムからikuraさんの本名を取得してみましょう。
🤔Q.yoasobiカラムから name = 'ikura'となっている人物のfull_nameの値を取得するには?
早速結論ですが、以下のクエリで求めることが出来ます。
回答例
--アーティスト「YOASOBI」をSTRUCT型で表現したクエリ
WITH struct_sample AS (
SELECT
STRUCT(
--活動開始日(DATE型)
DATE('2019-10-01') AS debut_date,
--活動継続中か(BOOL型)
TRUE AS is_active,
--メンバー情報(ARRAY<STRUCT>型)
[
--Ayaseの情報(STRUCT型)
STRUCT(
'Ayase' AS name
,'非公表' AS full_name
,'Composer' AS role
,31 AS age
),
--ikuraの情報(STRUCT型)
STRUCT(
'ikura' AS name
,'幾田りら' AS full_name
,'Vocalist' AS role
,25 AS age
)
] AS members,
--代表曲リスト(ARRAY<STRING>型)
['アイドル', '夜に駆ける', '群青'] AS hit_songs
) AS yoasobi
)
SELECT
member.full_name
FROM struct_sample
CROSS JOIN UNNEST(yoasobi.members) AS member
WHERE member.name = 'ikura'
;
わかりにくい部分はこの部分ですね。
FROM struct_sample
CROSS JOIN UNNEST(yoasobi.members) AS member
;
この部分を、UNNEST演算子のルール(詳しくはこちら)に対応させながら何が起こっているのかを確認していきます。
✅UNNEST演算子は引数として「FROM句で指定したソーステーブル」のARRAY型のカラムを取る
👉UNNEST演算子は引数としてソーステーブル「struct_sample」のARRAY型のカラム「yoasobi.members」を取っている。
👉「yoasobi」カラムはSTRUCT型なので、ドット演算子 (.) を使用して「members」フィールドにアクセスしている。
✅受け取ったARRAY内にある各値を、一組の行に変換(フラット化)する
👉受け取ったARRAY型のカラム「yoasobi.members」にある各値を一組の行に変換(フラット化)している
1行目は「Ayaseに関するSTRUCT」
2行目は「ikuraに関するSTRUCT」
ここまでの操作で出来上がるテーブルイメージは以下のようになります。
あとは簡単ですね。
👉WHERE句:「member」カラムはSTRUCT型なので、ドット演算子 (.) を使用して「name」フィールドにアクセスし、member.name = 'ikura'の行だけフィルタリング
👉SELECT句:「member」カラムはSTRUCT型なので、ドット演算子 (.) を使用して「full_name」フィールドにアクセスし抽出
最終的に以下の結果になります。
最後に、GA4データをBigQueryにエクスポートしたときに作成されるGA4イベントテーブルの「events_params」カラムも、同じようなデータ構造を持っていることを紹介して終わりたいと思います。
早速ですが以下のクエリを実行してみましょう。
疑似的にGA4イベントテーブルの構造を再現するクエリ
SELECT
'page_view' AS event_name,
1760686553983228 AS event_timestamp,
--event_paramsフィールド(ARRAY<STRUCT>)
[
STRUCT(
'page_title' AS key,
STRUCT(
'【BigQuery】STRUCT型って一体なに?' AS string_value,
NULL AS int_value,
NULL AS float_value,
NULL AS double_value
) AS value
),
STRUCT(
'ga_session_id' AS key,
STRUCT(
NULL AS string_value,
1760686553 AS int_value,
NULL AS float_value,
NULL AS double_value
) AS value
),
STRUCT(
'source' AS key,
STRUCT(
'google' AS string_value,
NULL AS int_value,
NULL AS float_value,
NULL AS double_value
) AS value
)
] AS event_params
;
実行結果は以下になります。
GA4イベントテーブルの「events_params」カラムとまったく同じ構造になっています!
「events_params」もARRAY型とSTRUCT型を組み合わせて表現されているんですね。
👉補足:「event_params」カラムはARRAY型
GA4イベントテーブルを成型するクエリ内では頻繁に以下のような操作を記述することがあると思います。
GA4イベントテーブルを成型するクエリ例
--GA4イベントテーブルをフラット化するよくあるクエリ
SELECT
event_name
,event_timestamp
,(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_title') AS page_title
........省略
--GA4イベントテーブル
FROM PROJECT.analytics_123456789.events_20251016
実は「event_params」がARRAY型なので、UNNEST演算子の引数にすることが可能なんです。
いかがだったでしょうか。今回は
をご紹介しました。
特にARRAY型×STRUCT型を組み合わせると、SQL内でかなり柔軟なデータ構造を定義することが可能になることがお判りいただけたかと思います。
GA4イベントテーブルをフラット化する際、何気なく実行していたクエリの理屈もご理解いただけたのではないでしょうか?
昨今、生成AIでほとんどのクエリを0から作成できるようになったわけですが、指示用プロンプトの質を高める要素の1つとして、今回ご紹介したような「データ構造への深い理解」は重要な要素である。と個人的には考えています。
社内にデータはたまっているけど活用方法のイメージが湧かない
そもそも自社にとってどんなデータを収集・蓄積すればいいのかわからない
広告を現在打っているが、利益に直結しているのかが不透明
私も含めData Dig(データディグ)に所属するデータアナリスト・データプランナーは「Data Dig(データディグ)」というCookieに依存しないデジタルマーケティング展開の支援も行っています。
これからのデジタルマーケティングは、自社の1st Partyデータ(顧客データ、購買履歴データ、CRM/SFAデータ)をいかに堅牢な構造で収集・活用するかが、ビジネス成長の鍵となります。
【Data Digがご支援できるデータ領域例】
GA4アクセスログ、1st Partyデータ(顧客データ、購買履歴データ、CRM/SFAデータ)などを利用した機械学習モデル構築相談
事業KPIに即したGA4に取り込むべきイベント設計/GTM設定
サーバーサイドGTMの導入
ADH, AMCをはじめとするData Crean Roomを用いた各種分析とインサイトの発見
社内の1st Partyデータを一元管理できるダッシュボード作成
広告効果検証用ダッシュボード作成
などなど、データ領域のご相談を幅広く承っております。
ここまで読んでいただきありがとうございました!😊
💡まずはお気軽にご相談ください
DataDigは、自社データをどう活かすかという戦略設計~データ活用実装まで伴走型でご支援します。御社の現状や課題に合わせた最適なデータ活用方法を一緒に検討いたします。ぜひお気軽にご相談ください。
📣CARTA ZEROが提供する統合デジタルマーケティングサービスの全容、また現状のデジタルマーケティング施策のノウハウを認識されたい場合は、ぜひ近日オープンした「KnowHowNow」をご覧ください。