[Looker] ExploreにExploreをjoinする #looker

2021.08.31

ExploreにExploreをjoinしたいと思ったことはないでしょうか?

Lookerではデータベースにあるテーブルをviewとして取り込み、分析に必要なviewをExploreで定義して、それに対して必要であれば別のviewをjoinしていきます。

そして、場合によってはこの状態が非正規化された1つの分析用のテーブルであるこがあると思います。このような場合、extendsを用いてより少ない記述でExploreを別のExploreにjoinをすることができます。

今回は、こちらの記事を参考に、extendsを用いたExplore同士のjoinについて紹介します。

利用ケース

extendsを利用して効率的に開発をすることができるケースとして、以下の二つがあげられます:

  • BigQueryをLookerに接続していて、UNNESTが必要なSTRUCT型やARRAY型でデータを格納しているテーブル同士をjoinしたい
  • 正規化してあるテーブルを非正規化してLooker上で扱いたい

実践

注文・顧客関連のひとまとまりのExploreを用意しました。これら一つ一つのExploreが分析用のテーブルと仮定します。

orders Explore(注文)

explore: orders {
  view_name: orders
  join: items {
    relationship: one_to_many
    sql_on: ${orders.items_id} = ${items.id} ;;
  }
}

users Explore(顧客)

explore: users {
  view_name: users
  join: address {
    relationship: one_to_many
    sql_on: ${users.id} = ${address.user_id} ;;
  }
}

extendsで参照するexploreにはview_nameを定義して置くことを推奨します。詳しくは下記記事をご覧ください。

extemdsを利用して売上Exploreに注文・顧客関連のExploreをjoinする

extendsを利用して、上記の注文・顧客関連の2つのExploreを、sales Explore(売上)にjoinします。

explore: sales {
  view_name: sales
  extends: [orders,users]
  join: orders {
    relationship: one_to_one
    sql_on: ${sales.order_id} = ${orders.id}
        and ${sales.slip_num} = ${orders.slip_num} ;;
  }
  join: users_join {
    from: users
    relationship: many_to_one
    sql_on: ${users.id} = ${orders.user_id} ;;
  }
}

これだけの記述ですが、Sales ExploreのUI画面ではAddressとItems viewも反映されています。

extendsは、拡張元と拡張先のオブジェクトにコンフリクトが生じた場合、継承先に定義されている定義が優先されます。そのため、orders Exploreとusers Exploreの基のview(base view)はいづれもsalesに上書きされてしまいます。

上書きされてしまったviewをsales Exploreにjoinすることで再定義しています。しかし、それぞれ参照されているExploreにjoinしているviewはコンフリクトしていないので上書きされずにUI上ではきちんと表示されています。

※ 今回の例ではview_nameを明示的に指定して置く必要はありませんでしたが、extendsを使用してExploreを定義する際には、エラーの原因になるので、明示的にview_nameを定義しておくことをお勧めします。

extendsを使わないと...

extendsを使用せずにsales Exploreを記述した場合のLookMLも載せておきます。

explore: sales {
  join: orders {
    relationship: one_to_one
    sql_on: ${sales.order_id} = ${orders.id}
        and ${sales.slip_num} = ${orders.slip_num} ;;
  }
  join: items {
    relationship: one_to_many
    sql_on: ${orders.items_id} = ${items.id} ;;
  }
  join: users_join {
    from: users
    relationship: many_to_one
    sql_on: ${users.id} = ${orders.user_id} ;;
  }
  join: address {
    relationship: one_to_many
    sql_on: ${users.id} = ${address.user_id} ;;
  }
}

今回の例では、各Exploreに1つのviewしかjoinしていないため、あまりありがたみがありませんが、実際の現場では多くのviewがjoinされているExplore同士をjoinすることがあると思います。

extendsを利用することで、はじめは可読性が低下してしまう側面があるのは否めません。

しかし、extendsを利用するとコードの再利用性と記述量を抑えることができるので、結果的に簡潔なコードで開発をすることができます。

まとめ

Exploreを書いていて、ひとまとまりのjoinの塊を定数的に定義しておきたい時に便利な方法をご紹介しました。

開発のお役に立てれば幸いです。