[Looker]LookML入門
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原則に基づいて複雑なクエリを作成できます。
また、LookMLはLookMLプロジェクト内で管理されます。
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 ;;
}
}
テーブルで定義すること
ここまでで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を理解する上でまず注目すべきこととしてはdimension
とdimension_group
、measure
でテーブルを定義することです。
dimension(ディメンション)
まずはテーブルの列情報をシンプル表現する方法としてディメンションがあります。
ディメンションはtype
とsql
を書くことによって一つのカラムを表現します。
dimension: total_amount {
type: number
sql: ${TABLE}.total_amount ;;
}
最初のうちはtype
とsql
を必要とする単一のカラム定義と覚えておくと良いでしょう。
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