複数のViewを結合する際、複数のViewで同じフィルターをかけたいという場面はないでしょうか? 例えば、OrdersビューとUsersビューを結合する際、同じ日付で絞り込みを行いたいというようなケースがあったとします。
これは別々のViewに存在するディメンションなのでExploreではViewごとにそれぞれフィルターを設定してもらうことになると思います。
とはいえこれは面倒なので、一つのフィルターを同時にOrders ViewとUsers Viewに適用する方法はないでしょうか。Filterパラメータを使えばできそうなので、ちょっと考えてみました。
orders.view に以下のようなフィルターを作成します
filter: date_filter {
view_label: "common filter"
description: "Please use this filter"
type: date
}
次に model ファイルに以下の sql_always_where
パラメータを設定します。
explore: order_items {
always_filter: {
filters: [date_filter: "7 days"]
}
sql_always_where: {% condition order_items.date_filter %} ${order_items.created_raw} {% endcondition %}
AND {% condition order_items.date_filter %} ${users.created_raw} {% endcondition %} ;;
join: users {
type: left_outer
sql_on: ${order_items.user_id} = ${users.id} ;;
relationship: many_to_one
}
}
元のDateディメンションをフィルターに使って欲しくない場合は、can_filter: no
を追加して明示的にフィルターとして使用できないようにしておくのも良いかと思います。
dimension_group: created {
type: time
timeframes: [time, hour, date, week, month, year, hour_of_day, day_of_week, month_num, raw, week_of_year,month_name]
sql: ${TABLE}.created_at ;;
can_filter: no
}
sql_always_where
に設定する場合、usersビューの結合が不要な場合でも常にJOINされてしまうので、以下のようにしてJOINされた時だけUsersビューの絞り込みが有効になるようにしても良いかもしれません。
explore: order_items {
always_filter: {
filters: [date_filter: "7 days"]
}
sql_always_where: {% condition order_items.date_filter %} ${order_items.created_raw} {% endcondition %} ;;
join: users {
type: left_outer
sql_on: ${order_items.user_id} = ${users.id} ;;
relationship: many_to_one
sql_where: {% condition order_items.date_filter %} ${users.created_raw} {% endcondition %} ;;
}
}
パターン1では絞り込みを実行する部分をExploreに追記する形にしましたが、これだとExploreに登場するたびに追記していく必要がありますので、これをViewレベルで制御する方法を考えてみます。
orders.view で以下のようなフィルターを作成します。
filter: date_filter {
view_label: "common filter"
description: "Please use this filter"
type: date
sql: {% condition date_filter %} TIMESTAMP(${order_items.created_date}) {% endcondition %}
AND {% condition date_filter %} TIMESTAMP(${users.created_date}) {% endcondition %}
;;
}
先ほどと異なるのは絞り込みの条件となるSQLをFilterに埋め込んでしまっている点です。そのため、Exploreでの定義は不要で、以下のように記述すればOKです。ただし、このフィルターはOrdersビューとUsersビューが結合されていることが前提となるので、注意が必要です。
explore: order_items {
always_filter: {
filters: [date_filter: "7 days"]
}
join: users {
type: left_outer
sql_on: ${order_items.user_id} = ${users.id} ;;
relationship: many_to_one
}
}
この他にも、派生テーブルを使用している場合には、サブクエリー内で(Viewを結合する前に)絞り込みを行っておく方法などもあるかと思います。
いずれにしてユースケースに応じて最適な方法を選んでいただければと思います。皆様の参考になれば幸いです。