[Looker]LookML入門

2023/08/10に公開

LookML入門

はじめに

この記事では LookMLの書き方を学習していく記事です。主な内容としては実践したときのメモを中心に書きます。(忘れやすいことなど)
誤りなどがあれば書き直していく予定です。なお、内容につきましては2023年8月9日時点の調査内容で記載しております。あらかじめご了承ください。

LookMLに入る前におさらい

さて本題ですが、LookMLとはそもそもどんなものだったでしょうかここで少しだけおさらいしましょう。

LookML は、Looker Modeling Language の略です。セマンティック データモデルを作成するために Looker で使用される言語です。LookML を使用して、SQL データベース内のディメンション、集計、計算、およびデータの関係を記述できます。

Looker は、LookML で記述されたモデルを使用して、特定のデータベースに対する SQL クエリを作成します。LookML は make のような依存関係言語で、C や Ruby といった命令型言語とは反対の性質を持ちます。

LookMLはデータモデリングのために定義済みのデータタイプと構文を提供します。
LookMLの構文は構造が明瞭で学びやすくなっています。(LookML を理解するためにプログラミング言語の経験は必要ありません。知っておくべきことはすべてここに記載されています。)

LookML は個々の SQL ダイアレクトには依存せず、SQL 式をカプセル化してあらゆる SQL 実装をサポートします。データ分析のために、LookML では DRY 原則(Don’t Repeat Yourself)に基づくスタイルを促進しています。

つまり、LookMLはLookerのためのデータモデリングとクエリ言語です。SQLを内包したデータ定義(スキーマ)を記述する言語とも言えます。※必ずしも内包する必要はありません。また、複雑なSQLを書くことなく、DRY原則に基づいて複雑なクエリを作成できます。

https://cloud.google.com/looker/docs/what-is-lookml?hl=ja#lookml_projects

また、LookMLはLookMLプロジェクト内で管理されます。

image

LookMLプロジェクトの構造
出典:https://cloud.google.com/looker/docs/what-is-lookml?hl=ja

基本的な概念

LookMLがどのような時に利用されるものかはよく理解できたと思います。ではLookMLにはどんな特徴があるのでしょうか。LookMLの基本概念として下記のようなものがあります。

項目 説明
モデル データベースへの接続情報を持つ。Exploresできる複数のViewを保存
ビュー データベース内のテーブルやビューに関する情報を保存
フィールド フィールドはデータベース内の個々のデータ要素を表現
ディメンション データを分類する要素であり、通常はフィルターやGROUP BYの基準として利用
メジャー 数値データであり、合計や平均などの計算を実行
表計算 抽出したデータを使ってセル単位の計算を実行

フィールドの集計や計算された値を指標はという形で表現します。
他にもダッシュボードやExploresなどありますが、モデルとビューを学習しないことには理解が難しいと考えられるため、今回は割愛します。
LookMLを理解するためにはまずLookMLの基本要素であるモデルとビューを理解するところからです。

LookMLの基本構造

モデルとビューを理解するためにまずはLookMLの基本構造を注意深くみていきましょう。
LookMLは独自の階層構造を持ち、ブロックによって階層が示されます。以下は基本的なLookMLの構造です。

view: order {
  sql_table_name: orders ; # データベース内のテーブル名
  dimension: created_at {
    type: date ; # ディメンションのデータ型
  }
  measure: total_amount {
    type: sum ; # メジャーの計算方法
    sql: amount ; # メジャーの計算式
  }
}

sql_table_nameは、LookMLのモデルで使用されるテーブルの名前を指定します。
他、dimensionとmeasureはテーブルのカラムに相当します。どのような役割を果たすのかは後ほど解説します。
まずはViewはテーブルであるということを念頭におきましょう。

派生テーブル

Viewはモデル内で定義されたテーブル名を指定することが一番スタンダードな方法ですが、それ以外に派生テーブルで指定する方法があり、主に2つあります。

  • Lookerベースで参照する方法
  • SQLベースで参照する方法

前者はネイティブ派生テーブル、後者はSQLベースの派生テーブルと呼びます。

項目 説明 指定方法
ネイティブ派生テーブル LookMLの構文で定義されたテーブル、Lookerベースで参照 derived_tableの定義した後にexplore_sourceを定義する
SQLベースの派生テーブル SQLベースで参照するテーブル、モデル内にあるテーブルに対してSQLクエリを実行して作成 derived_tableの定義した後にSQLを定義する

ネイティブ派生テーブルの例

view: customer_order_summary {
  derived_table: {
    explore_source: orders {
      column: customer_id {
        field: orders.customer_id
      }
      column: first_order {
        field: orders.first_order
      }
      column: total_amount {
        field: orders.total_amount
      }
    }
  }
  dimension: customer_id {
    type: number
    primary_key: yes
    sql: ${TABLE}.customer_id ;;
  }
  dimension_group: first_order {
    type: time
    timeframes: [date, week, month]
    sql: ${TABLE}.first_order ;;
  }
  dimension: total_amount {
    type: number
    value_format: "0.00"
    sql: ${TABLE}.total_amount ;;
  }
}

SQLベースの派生テーブルの例

view: customer_order_summary {
  derived_table: {
    sql:
      SELECT
        customer_id,
        MIN(DATE(time)) AS first_order,
        SUM(amount) AS total_amount
      FROM
        orders
      GROUP BY
        customer_id ;;
  }
  dimension: customer_id {
    type: number
    primary_key: yes
    sql: ${TABLE}.customer_id ;;
  }
  dimension_group: first_order {
    type: time
    timeframes: [date, week, month]
    sql: ${TABLE}.first_order ;;
  }
  dimension: total_amount {
    type: number
    value_format: "0.00"
    sql: ${TABLE}.total_amount ;;
  }
}

引用:ネイティブ派生テーブルとSQLベースの派生テーブル

テーブルで定義すること

ここまででViewにテーブルを定義する方法を説明しました。ではテーブルはどのように定義すれば良いのでしょうか。

LookML でテーブルを定義してみる

ここではSQLベースの派生テーブルを使って解説します。
※LookMLについては公式に掲載されているLookMLを修正して利用

view: customer_order_summary {
  derived_table: {
    sql:
      SELECT
        customer_id,
        MIN(DATE(time)) AS first_order,
        SUM(amount) AS total_amount
      FROM
        orders
      GROUP BY
        customer_id ;;
  }
  measure: count {
    type: count
    drill_fields: [detail*]
  }
  dimension: customer_id {
    type: number
    primary_key: yes
    sql: ${TABLE}.customer_id ;;
  }
  dimension_group: first_order {
    type: time
    timeframes: [date, week, month]
    sql: ${TABLE}.first_order ;;
  }
  dimension: total_amount {
    type: number
    value_format: "0.00"
    sql: ${TABLE}.total_amount ;;
  }

  set: detail {
    fields: [
        customer_id,
        first_order,
        total_amount
      ]
    }
}

上記のLookMLを理解する上でまず注目すべきこととしてはdimensiondimension_groupmeasureでテーブルを定義することです。

dimension(ディメンション)

まずはテーブルの列情報をシンプル表現する方法としてディメンションがあります。
ディメンションはtypesqlを書くことによって一つのカラムを表現します。

  dimension: total_amount {
    type: number
    sql: ${TABLE}.total_amount ;;
  }

最初のうちはtypesqlを必要とする単一のカラム定義と覚えておくと良いでしょう。

dimension_group(ディメンショングループ)

次にディメンショングループです。これは読んで字の如くディメンションのまとまりという意味です。
first_orderの例ではtime型のカラムが定義されており、さらにtimeframesによって分割されています。

つまり、first_orderというカラムでは日付単位(date)、週単位(week)、月単位(month)の3つにディメンションが分割されてグルーピングされています。

  dimension_group: first_order {
    type: time
    timeframes: [date, week, month]
    sql: ${TABLE}.first_order ;;
  }

最初のうちは一つのディメンションで複数のディメンションを定義できるのがディメンショングループであると覚えておくと良いでしょう。

補足:timeframesとは
少しだけ登場しましたので補足です。
LookMLのtimeframesは、データの期間を定義するものであり、データがどの期間にわたって集計されているか、またはレポートがどの期間にわたって表示されるかを指定します。timeframesは、次のいずれかの方法で指定できます。

  • 日付範囲: 日付範囲は、開始日と終了日で定義されます。
  • 期間: 期間は、期間の長さで定義されます。たとえば、1か月、1年、または5年などです。
  • 固定値: 固定値は、特定の日付または期間で定義されます。たとえば、2023年1月1日、または2023年第1四半期などです。

Lookerを使う側からすると「任意のデータを特定の期間に限定して検索する」という利用ケースに対応できます。

measure(メジャー)

最後にメジャーです。これはディメンションに対して計算を実行して新しいカラムを作成します。
データベースの分野においては関数従属したカラムを作ることと似ています。

  measure: count {
    type: count
  }

補足:カスタムメジャーと表計算
基本的なメジャーの他に決められた計算式を記述してカラムを作成することもできます。これをカスタムメジャーと言います。
例えば、Pointというカラムがあった時に35点以下ならRed、問題なければGreenと表示するカラムを作成できます。

また、SQLによって選択されているカラムを利用してシンプルな表計算を実行できます。カスタムメジャーと似ていますが、異なるところは選択されているカラムに対して有効であるということです。SQLによって選択されていない(射影されていない)カラムに表計算は利用できません。

データ型

ディメンションとメジャーについて理解を深めましたが、それぞれのカラムにはtypeという設定があります。
これは簡単に説明するとデータ型の指定です。Lookerではさまざまなデータ型が用意されています。

参考:Dimension, filter, and parameter types

※一部抜粋

  dimension: customer_id {
    type: number # データ型の指定
    primary_key: yes
    sql: ${TABLE}.customer_id ;;
  }
  dimension_group: first_order {
    type: time # データ型の指定
    timeframes: [date, week, month]
    sql: ${TABLE}.first_order ;;
  }

さまざまなデータ型がありますが、入門する上では以下の5つを基本として覚えておけば、だいたいの用途に対応できます。

  • number
  • string
  • time
  • date
  • date_time

※注意点
整数型にはint型が利用できるとも記載されていますが、REMOVED 5.4 Replaced by type: numberとあるので非推奨のデータ型です。numberを使いましょう。
他、間違えやすいポイントとしてはdateとdate_timeの違いです。日付だけでなく時間も指定したい場合はdate_timeを使いましょう。

補足:数値を計算で表現するか書式指定子で表現するか
だいたいどのような可視化でも全体のからの割合を表現したい時があります。
DBからデータを取り出したりpandasを使ってデータを取り出すなどしたとき、何かしらの計算を実行して実際に確認したい表示に修正するということがあります。

例えば、部分的な件数 / 全体の件数 = 割合 という計算の場合は割合を求める際に100倍にするという計算を実行すると思います。
Lookerでは書式指定子が用意されており、value_formatを用いることで表示されている数値の表現を変更できます。
また、小数点以下第何位まで対応するかという部分についてもvalue_formatで表現できます。

# 0.8という結果を80%として表示したい
  dimension: percent_data {
    type: number
    sql: ${TABLE}.percent_data ;;
    value_format: "0%"
  }
# 小数点以下第何位まで対応するか
# 0.8123という結果を0.81として表示したい
  dimension: percent_data {
    type: number
    sql: ${TABLE}.percent_data ;;
    value_format: "0.00"
  }

テンプレートフィルター

ここまででデータの取り出しと可視化までのデータ整形は可能ですが、入門レベルではもうひとおし覚えておきたい機能があります。
それがテンプレートフィルターです。どのような機能か説明するとLookMLに特定の条件式を埋め込み、ダッシュボードで操作できるようにしておく機能です。
テンプレートフィルタは、ビューのすべての行に適用されます。

以下の例では日付単位でフィルターをかけており、それを動的に変更できるようにしています。

view: customer_order_summary {
  derived_table: {
    sql:
      SELECT
        customer_id,
        MIN(DATE(time)) AS first_order,
        SUM(amount) AS total_amount
      FROM
        orders
      WHERE
        cast("date_time_data" as timestamp) AT TIME ZONE 'Asia/Tokyo'
      BETWEEN
        {% date_start date_filter %}
      AND
        {% date_end date_filter %}
       GROUP BY
       customer_id ;;
  }
  filter: date_filter{
    type: date
  }
  dimension: customer_id {
    type: number
    primary_key: yes
    sql: ${TABLE}.customer_id ;;
  }
  dimension_group: first_order {
    type: time
    timeframes: [date, week, month]
    sql: ${TABLE}.first_order ;;
  }
  dimension: total_amount {
    type: number
    value_format: "0.00"
    sql: ${TABLE}.total_amount ;;
  }
}

時間によるテンプレートフィルタは {% date_start date_filter %}{% date_end date_filter %}を記述し、filterでフィルター専用カラムを作成して表現します。

まとめ

  • Lookerには基本概念がある。主に以下の6点

    • モデル
    • ビュー
    • フィールド
    • ディメンション
    • メジャー
    • 表計算
  • LookMLは独自の階層構造を持ち、さまざまな設定項目がある。

    • sql_table_nameでテーブルを指定するのがベーシックな方法ではあるが、派生テーブルでテーブルを作成してそれをViewにすることもできる
  • さまざまなデータ型がある

    • number
    • string
    • time
    • date
    • date_time
  • 整数型に関してはintが非推奨である。dateとdate_timeは違う

  • Lookerではvalue_formatを使うなど計算以外に数値を変わった形で表現する方法がある

  • テンプレートフィルターをもちいることでユーザーが好きに入力できる動的なパラメータを設定できる

おわり

Discussion