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

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

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

2 0 962