
始める前に
- ラボでは、Google Cloud プロジェクトとリソースを一定の時間利用します
- ラボには時間制限があり、一時停止機能はありません。ラボを終了した場合は、最初からやり直す必要があります。
- 画面左上の [ラボを開始] をクリックして開始します
Create a new dataset and load JSON data into the table
/ 5
Creating arrays with ARRAY_AGG()
/ 5
Querying datasets that already have ARRAYs
/ 5
Explore a dataset with STRUCTs
/ 5
Practice with STRUCTs and ARRAYs
/ 5
BigQuery は、Google が低価格で提供する NoOps、フルマネージドの分析データベースです。BigQuery では、インフラストラクチャを所有して管理したりデータベース管理者を置いたりすることなく、テラバイト単位の大規模なデータでクエリを実行できます。また、SQL が採用されており、従量課金制というメリットもあります。このような特徴を活かし、ユーザーは有用な情報を得るためのデータ分析に専念できます。
このラボでは、BigQuery での半構造化データの操作(JSON や配列データ型の取り込み)について詳しく学習します。スキーマを非正規化し、ネストされた繰り返しのフィールドを持つ単一のテーブルにすることで、パフォーマンスが改善する場合があります。ただし、配列データを操作する SQL 構文は複雑になることがあります。ここでは、さまざまな半構造化データセットに対する読み込み、クエリ実行、トラブルシューティング、ネスト解除を実際に行います。
このラボでは、次のタスクについて学びます。
各ラボでは、新しい Google Cloud プロジェクトとリソースセットを一定時間無料で利用できます。
Qwiklabs にシークレット ウィンドウでログインします。
ラボのアクセス時間(例: 1:15:00
)に注意し、時間内に完了できるようにしてください。
一時停止機能はありません。必要な場合はやり直せますが、最初からになります。
準備ができたら、[ラボを開始] をクリックします。
ラボの認証情報(ユーザー名とパスワード)をメモしておきます。この情報は、Google Cloud Console にログインする際に使用します。
[Google Console を開く] をクリックします。
[別のアカウントを使用] をクリックし、このラボの認証情報をコピーしてプロンプトに貼り付けます。
他の認証情報を使用すると、エラーが発生したり、料金の請求が発生したりします。
利用規約に同意し、再設定用のリソースページをスキップします。
[Cloud Console の BigQuery へようこそ] メッセージ ボックスが開きます。このメッセージ ボックスにはクイックスタート ガイドへのリンクと、UI の更新情報が表示されます。
新しいデータセットに「fruit_store」という名前を付けます。その他のオプションはデフォルト値のままにします(データのロケーション、[デフォルトのテーブルの有効期限])。
[データセットを作成] をクリックします。
通常、SQL では、以下の果物リストのように各行に値が 1 つ含まれます。
行 |
果物 |
1 |
raspberry |
2 |
blackberry |
3 |
strawberry |
4 |
cherry |
果物リストに店舗の担当者名が必要な場合はどうすればよいでしょうか。次のようになります。
行 |
果物 |
担当者 |
1 |
raspberry |
sally |
2 |
blackberry |
sally |
3 |
strawberry |
sally |
4 |
cherry |
sally |
5 |
orange |
frederick |
6 |
apple |
frederick |
従来のリレーショナル データベースの SQL では、同じ名前が複数回出現する場合、上記のテーブルを果物と担当者の 2 つの別個のテーブルに分割することを考えます。これを正規化と呼びます(1 つのテーブルを多数のテーブルに分割)。mySQL のようなトランザクション データベースでよく行われます。
データ ウェアハウジングでよく行われるのはその逆の操作(非正規化)で、多数のテーブルを 1 つの大きなレポート テーブルにまとめます。
ここでは、繰り返しフィールドを使用して、粒度の異なるデータをすべて 1 つのテーブルに格納する方法を学びます。
行 |
果物(配列) |
担当者 |
1 |
raspberry |
sally |
blackberry | ||
strawberry | ||
cherry | ||
2 |
orange |
frederick |
apple |
上のテーブルの不自然な点はどこでしょうか。
ここからわかるのは、array
データ型が使用されているということです。
以下のように記述すると、果物の配列について理解しやすくなります。
行 |
果物(配列) |
担当者 |
1 |
[raspberry, blackberry, strawberry, cherry] |
sally |
2 |
[orange, apple] |
frederick |
これら両方のテーブルは同じ内容を表します。主な学習のポイントは 2 つあります。
実際に試す
[実行] をクリックします。
次のクエリを実行します。
次のようなエラーが表示されます。
Error: Array elements of types {INT64, STRING} do not have a common supertype at [3:1]
配列内では同じデータ型を使用する必要があります(すべて文字列、すべて数値など)。
[実行] をクリックします。
結果が表示されたら [JSON] タブをクリックして、ネストされた結果の構造を確認します。
BigQuery に JSON ファイルを取り込む必要がある場合はどうすればよいでしょうか。
fruit_store
データセットに新しいテーブルを作成します。cloud-training/data-insights-course/labs/optimizing-for-performance/shopping_cart.json
」新しいテーブルの名前を「fruit_details」にします。
[テーブルを作成] をクリックします。
スキーマで fruit_array
が「REPEATED」に設定されているため、このフィールドが配列であることがわかります。
内容のまとめ
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
今度は配列を自分のテーブル内に作成しましょう。
ARRAY_AGG()
関数を使用して、これらの文字列値を 1 つの配列にまとめます。以下のクエリをコピーして貼り付け、この一般公開データセットを探索します。ARRAY_LENGTH()
関数を使用して、閲覧されたページと商品の数を調べます。DISTINCT
を ARRAY_AGG()
に追加するだけです。内容のまとめ
次のように、配列に関連する便利な関数があります。
ARRAY_LENGTH(<array>)
で要素の数を調べるARRAY_AGG(DISTINCT <field>)
で要素の重複を除去するARRAY_AGG(<field> ORDER BY <field>)
で要素を並べ替えるARRAY_AGG(<field> LIMIT 5)
で要素の数を制限する[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
Google アナリティクス向けの BigQuery 一般公開データセット bigquery-public-data.google_analytics_sample
には、このコースのデータセット data-to-insights.ecommerce.all_sessions
より多くのフィールドと行が含まれています。さらに重要な点として、商品、ページ、トランザクションなどのフィールド値が、配列としてネイティブに格納されています。
[実行] をクリックしてクエリを実行します。
結果を右にスクロールして、hits.product.v2ProductName
フィールドを探します(複数フィールドのエイリアスについてはこの後で説明します)。
「Cannot access field product on a value with type ARRAY> at [5:8]
」というエラーが表示されます。
繰り返しフィールド(配列)を通常どおりにクエリするには、まず配列を分割して複数の行に戻す必要があります。
たとえば、hits.page.pageTitle
の配列は、次のように 1 つの行として格納されています。
これを次のようにする必要があります。
これを SQL で行うにはどうすればよいでしょうか。
UNNEST() については後ほど詳しく説明します。ここでは差し当たり、次のことを覚えておいてください。
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
フィールド エイリアスである hit.page.pageTitle
について、3 つのフィールドをドットで区切って 1 つにまとめたように見えるのが気になった方もいらっしゃるでしょう。配列値を使用すると、フィールドの粒度をより細かく「掘り下げる」ことができますが、これと同様に、関連するフィールドをグループ化してスキーマを「広げる」ことができるデータ型があります。それが、SQL データ型の STRUCT(構造体)です。
概念的には、構造体はメインテーブルに事前に結合された別テーブルのようなものと考えるとわかりやすくなります。
構造体には次のような特徴があります。
このように、構造体はテーブルによく似ています。
[エクスプローラ] で、bigquery-public-data データセットを探します。
まだ表示されていない場合は、[追加] > [名前を指定してプロジェクトにスターを付ける] をクリックします。
[プロジェクト名を入力] をクリックします。
「bigquery-public-data
」と入力して [スターを付ける] をクリックします。
固定されたプロジェクトのリストで [bigquery-public-data
] をクリックして開きます。
google_analytics_sample を探して開きます。
ga_sessions テーブルをクリックします。
スキーマをスクロールし、ブラウザの検索機能(Ctrl+F キー)を使って次の質問に答えてください。ヒント: カウントを開始する前にすべての列を開きます。
大きなレポート テーブルを構造体(事前に結合された「テーブル」)や配列(粒度が細かい)として格納すると、次のようなメリットがあります。
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
次のデータセットは、トラックを走るランナーのラップタイムです。各ラップは「スプリット」と呼ばれます。
行 |
runner.name |
runner.split |
1 |
Rudisha |
23.4 |
フィールドのエイリアスについて、どのようなことがわかりますか。構造体内にネストされているフィールドがあるため(name と split が runner のサブセット)、ドットを使用して区切りが示されています。
1 つのレースにランナーのスプリット タイムが複数ある場合はどうなるでしょうか(ラップごとのタイムなど)。
行 |
runner.name |
runner.splits |
1 |
Rudisha |
23.4 |
26.3 | ||
26.4 | ||
26.1 |
まとめると次のようになります。
「racing」という名前の新しいデータセットを作成します。
「race_results」という名前の新しいテーブルを作成します。
以下の Google Cloud Storage の JSON ファイルを取り込みます。
cloud-training/data-insights-course/labs/optimizing-for-performance/race_results.json
[テーブルを作成] をクリックします。
読み込みジョブが完了したら、新しく作成されたテーブルのスキーマをプレビューします。
構造体のフィールドはどれでしょうか。それを知る手掛かりは何ですか。
participants フィールドは RECORD 型なので構造体です。
配列のフィールドはどれでしょうか。
participants.splits
フィールドは、親である participants
構造体内の FLOAT の配列です。モードが REPEATED であるため、配列であることがわかります。この配列の値は、単一のフィールドに複数の値が含まれるため「ネストされた値」と呼ばれます。
何件の行が返されましたか。
解答: 1
各ランナーの名前とレースの種類を一覧表示するにはどうすればよいでしょうか。
Error: Cannot access field name on a value with type ARRAY\<STRUCT\<name STRING, splits ARRAY\<FLOAT64\>>>> at [1:21]
集計関数を使う際に GROUP BY を忘れた状態に似ています。ここでは、粒度の異なる 2 つの項目があります。レースが 1 行、参加者名が 3 行です。これをどのように変更すればよいでしょうか。
行 |
race |
participants.name |
1 |
800M |
Rudisha |
2 |
??? |
Makhloufi |
3 |
??? |
Murphy |
これを次のようにします。
行 |
race |
participants.name |
1 |
800M |
Rudisha |
2 |
800M |
Makhloufi |
3 |
800M |
Murphy |
従来のリレーショナル SQL では、レースのテーブルと参加者のテーブルがある場合、両方のテーブルから情報を取得するにはテーブルを結合する必要があります。ここでは、参加者の STRUCT(概念的にはテーブルによく似ています)は、すでにレースのテーブルには含まれていますが、STRUCT ではない「race」フィールドとはまだ適切に関連付けられていません。
最初のテーブルで 800M レースを各ランナーと関連付けるために使用する SQL コマンドは何ですか。
解答: CROSS JOIN
では、先に進みましょう。
Error: Table name "participants" cannot be resolved: dataset name is missing
.
参加者の STRUCT はテーブルに似ていますが、技術的には racing.race_results
テーブル内のフィールドの 1 つです。
効果がありました。各レースのランナーがすべて一覧表示されました。
行 |
race |
name |
1 |
800M |
Rudisha |
2 |
800M |
Makhloufi |
3 |
800M |
Murphy |
4 |
800M |
Bosse |
5 |
800M |
Rotich |
6 |
800M |
Lewandowski |
7 |
800M |
Kipketer |
8 |
800M |
Berian |
以下の方法で最後のクエリを簡素化できます。
これで同じクエリ結果が得られます。
レースの種類が複数ある場合(800M、100M、200M)、クロス結合では、デカルト積のように各ランナーの名前がすべてのレースと関連付けられることはないのでしょうか。
解答: そのようにはなりません。これは相関クロス結合であり、個々の行に関連付けられた要素のみが展開されます。詳しくは、配列と構造体の操作をご覧ください。
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
構造体のまとめ:
STRUCT(
"Rudisha" as name, [23.4, 26.3, 26.4, 26.1] as splits
)
AS runner
先ほど作成した racing.race_results
テーブルを使用して以下の質問に解答してください。
タスク: 参加したランナーの合計数を取得するクエリを作成してください。
解答例:
行 |
racer_count |
1 |
8 |
解答: レースに参加したランナーは 8 人です。
名前が「R」で始まるランナーの合計レース時間を一覧表示するクエリを作成します。合計時間が短いランナーが先に表示されるように並べ替えます。UNNEST() 演算子を使って、部分的に作成済みの次のクエリで作業を開始します。
解答例:
行 |
name |
total_race_time |
1 |
Rudisha |
102.19999999999999 |
2 |
Rotich |
103.6 |
800M のレースで最も速いラップタイムは、23.2 秒でした。ただし、それがどのランナーの記録であるかは確認できていません。その結果を返すクエリを作成します。
解答例:
行 |
name |
split_time |
1 |
Kipketer |
23.2 |
JSON データセットを取り込み、配列と構造体を作成し、半構造化データをネスト解除して分析情報を得ることができました。
詳しくは、配列の操作をご覧ください。
Copyright 2020 Google LLC All rights reserved. Google および Google のロゴは Google LLC の商標です。その他すべての企業名および商品名はそれぞれ各社の商標または登録商標です。
このコンテンツは現在ご利用いただけません
利用可能になりましたら、メールでお知らせいたします
ありがとうございます。
利用可能になりましたら、メールでご連絡いたします
1 回に 1 つのラボ
既存のラボをすべて終了して、このラボを開始することを確認してください