Question

一つのフィルターを複数のViewに適用する

  • 11 September 2020
  • 0 replies
  • 273 views

Userlevel 2

複数のViewを結合する際、複数のViewで同じフィルターをかけたいという場面はないでしょうか? 例えば、OrdersビューとUsersビューを結合する際、同じ日付で絞り込みを行いたいというようなケースがあったとします。


これは別々のViewに存在するディメンションなのでExploreではViewごとにそれぞれフィルターを設定してもらうことになると思います。



とはいえこれは面倒なので、一つのフィルターを同時にOrders ViewとUsers Viewに適用する方法はないでしょうか。Filterパラメータを使えばできそうなので、ちょっと考えてみました。


パターン1


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 %} ;;
}
}



この場合、Usersビューのフィールドを選択しない場合はLEFT JOINが行われません。


パターン2


パターン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を結合する前に)絞り込みを行っておく方法などもあるかと思います。


いずれにしてユースケースに応じて最適な方法を選んでいただければと思います。皆様の参考になれば幸いです。


0 replies

Be the first to reply!

Reply