From 87076d95beccf5c9353971d222ca359a0f336139 Mon Sep 17 00:00:00 2001 From: Courtney Holcomb Date: Thu, 14 Nov 2024 08:35:12 -0800 Subject: [PATCH] WIP - debug issues with derived offset metric filters --- .../simple_manifest/metrics.yaml | 7 +- .../dataflow/builder/dataflow_plan_builder.py | 70 +- ...d_where_constraint_not_selected__plan0.sql | 762 ++++++++++-------- ...nstraint_not_selected__plan0_optimized.sql | 64 +- 4 files changed, 512 insertions(+), 391 deletions(-) diff --git a/metricflow-semantics/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/metrics.yaml b/metricflow-semantics/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/metrics.yaml index fe28fb047..50608f961 100644 --- a/metricflow-semantics/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/metrics.yaml +++ b/metricflow-semantics/metricflow_semantics/test_helpers/semantic_manifest_yamls/simple_manifest/metrics.yaml @@ -700,7 +700,7 @@ metric: alias: bookings_2_weeks_ago --- metric: - name: "bookings_offset_once" + name: bookings_offset_once description: bookings metric offset once. type: derived type_params: @@ -708,9 +708,11 @@ metric: metrics: - name: bookings offset_window: 5 days + filter: "{{ Entity('listing') }} IS NOT NULL" --- metric: - name: "bookings_offset_twice" + # TODO: rename this metric in a later commit + name: bookings_offset_twice description: bookings metric offset twice. type: derived type_params: @@ -718,6 +720,7 @@ metric: metrics: - name: bookings_offset_once offset_window: 2 days + filter: "{{ Dimension('booking__is_instant') }}" --- metric: name: bookings_at_start_of_month diff --git a/metricflow/dataflow/builder/dataflow_plan_builder.py b/metricflow/dataflow/builder/dataflow_plan_builder.py index c7cdc5ebb..9d6b7d55d 100644 --- a/metricflow/dataflow/builder/dataflow_plan_builder.py +++ b/metricflow/dataflow/builder/dataflow_plan_builder.py @@ -584,19 +584,18 @@ def _build_derived_metric_output_node( parent_nodes: List[DataflowPlanNode] = [] - # This is the filter that's defined for the metric in the configs. - metric_definition_filter_specs = filter_spec_factory.create_from_where_filter_intersection( + # These are the filters defined on the outer metric (the derived metric). + # how did we get the specs in here in the first place? + outer_metric_definition_filter_specs = filter_spec_factory.create_from_where_filter_intersection( filter_location=WhereFilterLocation.for_metric(metric_spec.reference), filter_intersection=metric.filter, ) - + outer_metric_filter_spec_set = WhereFilterSpecSet( + metric_level_filter_specs=tuple(outer_metric_definition_filter_specs), + ) for metric_input_spec in metric_input_specs: - where_filter_spec_set = WhereFilterSpecSet( - metric_level_filter_specs=tuple(metric_definition_filter_specs), - ) - - # These are the filters that's defined as part of the input metric. - where_filter_spec_set = where_filter_spec_set.merge(metric_input_spec.filter_spec_set) + # Add the filters defined on each input metric. + input_metric_where_filter_spec_set = outer_metric_filter_spec_set.merge(metric_input_spec.filter_spec_set) # If metric is offset, we'll apply where constraint after offset to avoid removing values # unexpectedly. Time constraint will be applied by INNER JOINing to time spine. @@ -604,32 +603,47 @@ def _build_derived_metric_output_node( # is about post-join to pre-join for dimension access, and relies on the builder to collect # predicates from query and metric specs and make them available at measure level. if not metric_spec.has_time_offset: - where_filter_spec_set = where_filter_spec_set.merge(metric_spec.filter_spec_set) + input_metric_where_filter_spec_set = input_metric_where_filter_spec_set.merge( + metric_spec.filter_spec_set + ) metric_pushdown_state = ( predicate_pushdown_state if not metric_spec.has_time_offset else PredicatePushdownState.with_pushdown_disabled() ) - - parent_nodes.append( - self._build_any_metric_output_node( - BuildAnyMetricOutputNodeParameterSet( - metric_spec=MetricSpec( - element_name=metric_input_spec.element_name, - filter_spec_set=where_filter_spec_set, - alias=metric_input_spec.alias, - offset_window=metric_input_spec.offset_window, - offset_to_grain=metric_input_spec.offset_to_grain, - ), - queried_linkable_specs=( - queried_linkable_specs if not metric_spec.has_time_offset else required_linkable_specs - ), - filter_spec_factory=filter_spec_factory, - predicate_pushdown_state=metric_pushdown_state, - for_group_by_source_node=False, - ) + # Need to include any outer metric filters when building the input metric, EXCEPT metric_time filters which should be saved for the outer metric + # How to apply those metric_time filters to the outer metric? Will metric_time be available at the top-level? Do we require it for offset metrics? + # I think so. but why couldn't we do that for join_to_timespine metrics? I think there was a reason. Go back to read that logic. Likely will copy it. + # Ok so separate metric_time from other filters (for the outer metric filters and query-level filters). I think we might need to take those filters + # and apply them to the offset column. Is that possible? Will it get messed up if there are custom grains? A lot to work out here!!! + input_metric_parent_node = self._build_any_metric_output_node( + BuildAnyMetricOutputNodeParameterSet( + metric_spec=MetricSpec( + element_name=metric_input_spec.element_name, + filter_spec_set=input_metric_where_filter_spec_set, + alias=metric_input_spec.alias, + offset_window=metric_input_spec.offset_window, + offset_to_grain=metric_input_spec.offset_to_grain, + ), + queried_linkable_specs=( + # If there is an offset, we need to include filter specs when we aggregating the input metric + # so that they will be available to the outer metric. + # Is that right?? That seems wrong! This might be a bug! + # Write a test for this case. what is it? + # A derived metric with tiered filters of different specs. One on the input metric, one on the outer metric. + # That's the simple case. Then write another test with approximately the same metric, but with an offset on that input metric. + # Do the specs get filtered appropriately at the input metric level before aggregation? If not, is it possible to fix that? + queried_linkable_specs + # Logic below was wrong! + # if not metric_spec.has_time_offset + # else required_linkable_specs + ), + filter_spec_factory=filter_spec_factory, + predicate_pushdown_state=metric_pushdown_state, + for_group_by_source_node=False, ) ) + parent_nodes.append(input_metric_parent_node) parent_node = ( parent_nodes[0] diff --git a/tests_metricflow/snapshots/test_derived_metric_rendering.py/SqlQueryPlan/DuckDB/test_nested_derived_metric_offset_with_joined_where_constraint_not_selected__plan0.sql b/tests_metricflow/snapshots/test_derived_metric_rendering.py/SqlQueryPlan/DuckDB/test_nested_derived_metric_offset_with_joined_where_constraint_not_selected__plan0.sql index a2c06603c..168c7c528 100644 --- a/tests_metricflow/snapshots/test_derived_metric_rendering.py/SqlQueryPlan/DuckDB/test_nested_derived_metric_offset_with_joined_where_constraint_not_selected__plan0.sql +++ b/tests_metricflow/snapshots/test_derived_metric_rendering.py/SqlQueryPlan/DuckDB/test_nested_derived_metric_offset_with_joined_where_constraint_not_selected__plan0.sql @@ -4,370 +4,466 @@ sql_engine: DuckDB --- -- Compute Metrics via Expressions SELECT - subq_13.metric_time__day + subq_14.metric_time__day , 2 * bookings_offset_once AS bookings_offset_twice FROM ( -- Pass Only Elements: ['metric_time__day', 'bookings_offset_once'] SELECT - subq_12.metric_time__day - , subq_12.bookings_offset_once + subq_13.metric_time__day + , subq_13.bookings_offset_once FROM ( -- Constrain Output with WHERE SELECT - subq_11.metric_time__day - , subq_11.booking__is_instant - , subq_11.bookings_offset_once + subq_12.metric_time__day + , subq_12.bookings_offset_once FROM ( -- Join to Time Spine Dataset SELECT - subq_9.metric_time__day AS metric_time__day - , subq_8.booking__is_instant AS booking__is_instant - , subq_8.bookings_offset_once AS bookings_offset_once + subq_10.metric_time__day AS metric_time__day + , subq_9.bookings_offset_once AS bookings_offset_once FROM ( -- Time Spine SELECT - subq_10.ds AS metric_time__day - FROM ***************************.mf_time_spine subq_10 - ) subq_9 + subq_11.ds AS metric_time__day + FROM ***************************.mf_time_spine subq_11 + ) subq_10 INNER JOIN ( -- Compute Metrics via Expressions SELECT - subq_7.metric_time__day - , subq_7.booking__is_instant + subq_8.metric_time__day , 2 * bookings AS bookings_offset_once FROM ( -- Compute Metrics via Expressions SELECT - subq_6.metric_time__day - , subq_6.booking__is_instant - , subq_6.bookings + subq_7.metric_time__day + , subq_7.bookings FROM ( -- Aggregate Measures SELECT - subq_5.metric_time__day - , subq_5.booking__is_instant - , SUM(subq_5.bookings) AS bookings + subq_6.metric_time__day + , SUM(subq_6.bookings) AS bookings FROM ( - -- Pass Only Elements: ['bookings', 'booking__is_instant', 'metric_time__day'] + -- Pass Only Elements: ['bookings', 'metric_time__day'] SELECT - subq_4.metric_time__day - , subq_4.booking__is_instant - , subq_4.bookings + subq_5.metric_time__day + , subq_5.bookings FROM ( - -- Join to Time Spine Dataset + -- Constrain Output with WHERE SELECT - subq_2.metric_time__day AS metric_time__day - , DATE_TRUNC('week', subq_2.metric_time__day) AS metric_time__week - , DATE_TRUNC('month', subq_2.metric_time__day) AS metric_time__month - , DATE_TRUNC('quarter', subq_2.metric_time__day) AS metric_time__quarter - , DATE_TRUNC('year', subq_2.metric_time__day) AS metric_time__year - , EXTRACT(year FROM subq_2.metric_time__day) AS metric_time__extract_year - , EXTRACT(quarter FROM subq_2.metric_time__day) AS metric_time__extract_quarter - , EXTRACT(month FROM subq_2.metric_time__day) AS metric_time__extract_month - , EXTRACT(day FROM subq_2.metric_time__day) AS metric_time__extract_day - , EXTRACT(isodow FROM subq_2.metric_time__day) AS metric_time__extract_dow - , EXTRACT(doy FROM subq_2.metric_time__day) AS metric_time__extract_doy - , subq_1.ds__day AS ds__day - , subq_1.ds__week AS ds__week - , subq_1.ds__month AS ds__month - , subq_1.ds__quarter AS ds__quarter - , subq_1.ds__year AS ds__year - , subq_1.ds__extract_year AS ds__extract_year - , subq_1.ds__extract_quarter AS ds__extract_quarter - , subq_1.ds__extract_month AS ds__extract_month - , subq_1.ds__extract_day AS ds__extract_day - , subq_1.ds__extract_dow AS ds__extract_dow - , subq_1.ds__extract_doy AS ds__extract_doy - , subq_1.ds_partitioned__day AS ds_partitioned__day - , subq_1.ds_partitioned__week AS ds_partitioned__week - , subq_1.ds_partitioned__month AS ds_partitioned__month - , subq_1.ds_partitioned__quarter AS ds_partitioned__quarter - , subq_1.ds_partitioned__year AS ds_partitioned__year - , subq_1.ds_partitioned__extract_year AS ds_partitioned__extract_year - , subq_1.ds_partitioned__extract_quarter AS ds_partitioned__extract_quarter - , subq_1.ds_partitioned__extract_month AS ds_partitioned__extract_month - , subq_1.ds_partitioned__extract_day AS ds_partitioned__extract_day - , subq_1.ds_partitioned__extract_dow AS ds_partitioned__extract_dow - , subq_1.ds_partitioned__extract_doy AS ds_partitioned__extract_doy - , subq_1.paid_at__day AS paid_at__day - , subq_1.paid_at__week AS paid_at__week - , subq_1.paid_at__month AS paid_at__month - , subq_1.paid_at__quarter AS paid_at__quarter - , subq_1.paid_at__year AS paid_at__year - , subq_1.paid_at__extract_year AS paid_at__extract_year - , subq_1.paid_at__extract_quarter AS paid_at__extract_quarter - , subq_1.paid_at__extract_month AS paid_at__extract_month - , subq_1.paid_at__extract_day AS paid_at__extract_day - , subq_1.paid_at__extract_dow AS paid_at__extract_dow - , subq_1.paid_at__extract_doy AS paid_at__extract_doy - , subq_1.booking__ds__day AS booking__ds__day - , subq_1.booking__ds__week AS booking__ds__week - , subq_1.booking__ds__month AS booking__ds__month - , subq_1.booking__ds__quarter AS booking__ds__quarter - , subq_1.booking__ds__year AS booking__ds__year - , subq_1.booking__ds__extract_year AS booking__ds__extract_year - , subq_1.booking__ds__extract_quarter AS booking__ds__extract_quarter - , subq_1.booking__ds__extract_month AS booking__ds__extract_month - , subq_1.booking__ds__extract_day AS booking__ds__extract_day - , subq_1.booking__ds__extract_dow AS booking__ds__extract_dow - , subq_1.booking__ds__extract_doy AS booking__ds__extract_doy - , subq_1.booking__ds_partitioned__day AS booking__ds_partitioned__day - , subq_1.booking__ds_partitioned__week AS booking__ds_partitioned__week - , subq_1.booking__ds_partitioned__month AS booking__ds_partitioned__month - , subq_1.booking__ds_partitioned__quarter AS booking__ds_partitioned__quarter - , subq_1.booking__ds_partitioned__year AS booking__ds_partitioned__year - , subq_1.booking__ds_partitioned__extract_year AS booking__ds_partitioned__extract_year - , subq_1.booking__ds_partitioned__extract_quarter AS booking__ds_partitioned__extract_quarter - , subq_1.booking__ds_partitioned__extract_month AS booking__ds_partitioned__extract_month - , subq_1.booking__ds_partitioned__extract_day AS booking__ds_partitioned__extract_day - , subq_1.booking__ds_partitioned__extract_dow AS booking__ds_partitioned__extract_dow - , subq_1.booking__ds_partitioned__extract_doy AS booking__ds_partitioned__extract_doy - , subq_1.booking__paid_at__day AS booking__paid_at__day - , subq_1.booking__paid_at__week AS booking__paid_at__week - , subq_1.booking__paid_at__month AS booking__paid_at__month - , subq_1.booking__paid_at__quarter AS booking__paid_at__quarter - , subq_1.booking__paid_at__year AS booking__paid_at__year - , subq_1.booking__paid_at__extract_year AS booking__paid_at__extract_year - , subq_1.booking__paid_at__extract_quarter AS booking__paid_at__extract_quarter - , subq_1.booking__paid_at__extract_month AS booking__paid_at__extract_month - , subq_1.booking__paid_at__extract_day AS booking__paid_at__extract_day - , subq_1.booking__paid_at__extract_dow AS booking__paid_at__extract_dow - , subq_1.booking__paid_at__extract_doy AS booking__paid_at__extract_doy - , subq_1.listing AS listing - , subq_1.guest AS guest - , subq_1.host AS host - , subq_1.booking__listing AS booking__listing - , subq_1.booking__guest AS booking__guest - , subq_1.booking__host AS booking__host - , subq_1.is_instant AS is_instant - , subq_1.booking__is_instant AS booking__is_instant - , subq_1.bookings AS bookings - , subq_1.instant_bookings AS instant_bookings - , subq_1.booking_value AS booking_value - , subq_1.max_booking_value AS max_booking_value - , subq_1.min_booking_value AS min_booking_value - , subq_1.bookers AS bookers - , subq_1.average_booking_value AS average_booking_value - , subq_1.referred_bookings AS referred_bookings - , subq_1.median_booking_value AS median_booking_value - , subq_1.booking_value_p99 AS booking_value_p99 - , subq_1.discrete_booking_value_p99 AS discrete_booking_value_p99 - , subq_1.approximate_continuous_booking_value_p99 AS approximate_continuous_booking_value_p99 - , subq_1.approximate_discrete_booking_value_p99 AS approximate_discrete_booking_value_p99 + subq_4.metric_time__day + , subq_4.metric_time__week + , subq_4.metric_time__month + , subq_4.metric_time__quarter + , subq_4.metric_time__year + , subq_4.metric_time__extract_year + , subq_4.metric_time__extract_quarter + , subq_4.metric_time__extract_month + , subq_4.metric_time__extract_day + , subq_4.metric_time__extract_dow + , subq_4.metric_time__extract_doy + , subq_4.ds__day + , subq_4.ds__week + , subq_4.ds__month + , subq_4.ds__quarter + , subq_4.ds__year + , subq_4.ds__extract_year + , subq_4.ds__extract_quarter + , subq_4.ds__extract_month + , subq_4.ds__extract_day + , subq_4.ds__extract_dow + , subq_4.ds__extract_doy + , subq_4.ds_partitioned__day + , subq_4.ds_partitioned__week + , subq_4.ds_partitioned__month + , subq_4.ds_partitioned__quarter + , subq_4.ds_partitioned__year + , subq_4.ds_partitioned__extract_year + , subq_4.ds_partitioned__extract_quarter + , subq_4.ds_partitioned__extract_month + , subq_4.ds_partitioned__extract_day + , subq_4.ds_partitioned__extract_dow + , subq_4.ds_partitioned__extract_doy + , subq_4.paid_at__day + , subq_4.paid_at__week + , subq_4.paid_at__month + , subq_4.paid_at__quarter + , subq_4.paid_at__year + , subq_4.paid_at__extract_year + , subq_4.paid_at__extract_quarter + , subq_4.paid_at__extract_month + , subq_4.paid_at__extract_day + , subq_4.paid_at__extract_dow + , subq_4.paid_at__extract_doy + , subq_4.booking__ds__day + , subq_4.booking__ds__week + , subq_4.booking__ds__month + , subq_4.booking__ds__quarter + , subq_4.booking__ds__year + , subq_4.booking__ds__extract_year + , subq_4.booking__ds__extract_quarter + , subq_4.booking__ds__extract_month + , subq_4.booking__ds__extract_day + , subq_4.booking__ds__extract_dow + , subq_4.booking__ds__extract_doy + , subq_4.booking__ds_partitioned__day + , subq_4.booking__ds_partitioned__week + , subq_4.booking__ds_partitioned__month + , subq_4.booking__ds_partitioned__quarter + , subq_4.booking__ds_partitioned__year + , subq_4.booking__ds_partitioned__extract_year + , subq_4.booking__ds_partitioned__extract_quarter + , subq_4.booking__ds_partitioned__extract_month + , subq_4.booking__ds_partitioned__extract_day + , subq_4.booking__ds_partitioned__extract_dow + , subq_4.booking__ds_partitioned__extract_doy + , subq_4.booking__paid_at__day + , subq_4.booking__paid_at__week + , subq_4.booking__paid_at__month + , subq_4.booking__paid_at__quarter + , subq_4.booking__paid_at__year + , subq_4.booking__paid_at__extract_year + , subq_4.booking__paid_at__extract_quarter + , subq_4.booking__paid_at__extract_month + , subq_4.booking__paid_at__extract_day + , subq_4.booking__paid_at__extract_dow + , subq_4.booking__paid_at__extract_doy + , subq_4.listing + , subq_4.guest + , subq_4.host + , subq_4.booking__listing + , subq_4.booking__guest + , subq_4.booking__host + , subq_4.is_instant + , subq_4.booking__is_instant + , subq_4.bookings + , subq_4.instant_bookings + , subq_4.booking_value + , subq_4.max_booking_value + , subq_4.min_booking_value + , subq_4.bookers + , subq_4.average_booking_value + , subq_4.referred_bookings + , subq_4.median_booking_value + , subq_4.booking_value_p99 + , subq_4.discrete_booking_value_p99 + , subq_4.approximate_continuous_booking_value_p99 + , subq_4.approximate_discrete_booking_value_p99 FROM ( - -- Time Spine - SELECT - subq_3.ds AS metric_time__day - FROM ***************************.mf_time_spine subq_3 - ) subq_2 - INNER JOIN ( - -- Metric Time Dimension 'ds' + -- Join to Time Spine Dataset SELECT - subq_0.ds__day - , subq_0.ds__week - , subq_0.ds__month - , subq_0.ds__quarter - , subq_0.ds__year - , subq_0.ds__extract_year - , subq_0.ds__extract_quarter - , subq_0.ds__extract_month - , subq_0.ds__extract_day - , subq_0.ds__extract_dow - , subq_0.ds__extract_doy - , subq_0.ds_partitioned__day - , subq_0.ds_partitioned__week - , subq_0.ds_partitioned__month - , subq_0.ds_partitioned__quarter - , subq_0.ds_partitioned__year - , subq_0.ds_partitioned__extract_year - , subq_0.ds_partitioned__extract_quarter - , subq_0.ds_partitioned__extract_month - , subq_0.ds_partitioned__extract_day - , subq_0.ds_partitioned__extract_dow - , subq_0.ds_partitioned__extract_doy - , subq_0.paid_at__day - , subq_0.paid_at__week - , subq_0.paid_at__month - , subq_0.paid_at__quarter - , subq_0.paid_at__year - , subq_0.paid_at__extract_year - , subq_0.paid_at__extract_quarter - , subq_0.paid_at__extract_month - , subq_0.paid_at__extract_day - , subq_0.paid_at__extract_dow - , subq_0.paid_at__extract_doy - , subq_0.booking__ds__day - , subq_0.booking__ds__week - , subq_0.booking__ds__month - , subq_0.booking__ds__quarter - , subq_0.booking__ds__year - , subq_0.booking__ds__extract_year - , subq_0.booking__ds__extract_quarter - , subq_0.booking__ds__extract_month - , subq_0.booking__ds__extract_day - , subq_0.booking__ds__extract_dow - , subq_0.booking__ds__extract_doy - , subq_0.booking__ds_partitioned__day - , subq_0.booking__ds_partitioned__week - , subq_0.booking__ds_partitioned__month - , subq_0.booking__ds_partitioned__quarter - , subq_0.booking__ds_partitioned__year - , subq_0.booking__ds_partitioned__extract_year - , subq_0.booking__ds_partitioned__extract_quarter - , subq_0.booking__ds_partitioned__extract_month - , subq_0.booking__ds_partitioned__extract_day - , subq_0.booking__ds_partitioned__extract_dow - , subq_0.booking__ds_partitioned__extract_doy - , subq_0.booking__paid_at__day - , subq_0.booking__paid_at__week - , subq_0.booking__paid_at__month - , subq_0.booking__paid_at__quarter - , subq_0.booking__paid_at__year - , subq_0.booking__paid_at__extract_year - , subq_0.booking__paid_at__extract_quarter - , subq_0.booking__paid_at__extract_month - , subq_0.booking__paid_at__extract_day - , subq_0.booking__paid_at__extract_dow - , subq_0.booking__paid_at__extract_doy - , subq_0.ds__day AS metric_time__day - , subq_0.ds__week AS metric_time__week - , subq_0.ds__month AS metric_time__month - , subq_0.ds__quarter AS metric_time__quarter - , subq_0.ds__year AS metric_time__year - , subq_0.ds__extract_year AS metric_time__extract_year - , subq_0.ds__extract_quarter AS metric_time__extract_quarter - , subq_0.ds__extract_month AS metric_time__extract_month - , subq_0.ds__extract_day AS metric_time__extract_day - , subq_0.ds__extract_dow AS metric_time__extract_dow - , subq_0.ds__extract_doy AS metric_time__extract_doy - , subq_0.listing - , subq_0.guest - , subq_0.host - , subq_0.booking__listing - , subq_0.booking__guest - , subq_0.booking__host - , subq_0.is_instant - , subq_0.booking__is_instant - , subq_0.bookings - , subq_0.instant_bookings - , subq_0.booking_value - , subq_0.max_booking_value - , subq_0.min_booking_value - , subq_0.bookers - , subq_0.average_booking_value - , subq_0.referred_bookings - , subq_0.median_booking_value - , subq_0.booking_value_p99 - , subq_0.discrete_booking_value_p99 - , subq_0.approximate_continuous_booking_value_p99 - , subq_0.approximate_discrete_booking_value_p99 + subq_2.metric_time__day AS metric_time__day + , DATE_TRUNC('week', subq_2.metric_time__day) AS metric_time__week + , DATE_TRUNC('month', subq_2.metric_time__day) AS metric_time__month + , DATE_TRUNC('quarter', subq_2.metric_time__day) AS metric_time__quarter + , DATE_TRUNC('year', subq_2.metric_time__day) AS metric_time__year + , EXTRACT(year FROM subq_2.metric_time__day) AS metric_time__extract_year + , EXTRACT(quarter FROM subq_2.metric_time__day) AS metric_time__extract_quarter + , EXTRACT(month FROM subq_2.metric_time__day) AS metric_time__extract_month + , EXTRACT(day FROM subq_2.metric_time__day) AS metric_time__extract_day + , EXTRACT(isodow FROM subq_2.metric_time__day) AS metric_time__extract_dow + , EXTRACT(doy FROM subq_2.metric_time__day) AS metric_time__extract_doy + , subq_1.ds__day AS ds__day + , subq_1.ds__week AS ds__week + , subq_1.ds__month AS ds__month + , subq_1.ds__quarter AS ds__quarter + , subq_1.ds__year AS ds__year + , subq_1.ds__extract_year AS ds__extract_year + , subq_1.ds__extract_quarter AS ds__extract_quarter + , subq_1.ds__extract_month AS ds__extract_month + , subq_1.ds__extract_day AS ds__extract_day + , subq_1.ds__extract_dow AS ds__extract_dow + , subq_1.ds__extract_doy AS ds__extract_doy + , subq_1.ds_partitioned__day AS ds_partitioned__day + , subq_1.ds_partitioned__week AS ds_partitioned__week + , subq_1.ds_partitioned__month AS ds_partitioned__month + , subq_1.ds_partitioned__quarter AS ds_partitioned__quarter + , subq_1.ds_partitioned__year AS ds_partitioned__year + , subq_1.ds_partitioned__extract_year AS ds_partitioned__extract_year + , subq_1.ds_partitioned__extract_quarter AS ds_partitioned__extract_quarter + , subq_1.ds_partitioned__extract_month AS ds_partitioned__extract_month + , subq_1.ds_partitioned__extract_day AS ds_partitioned__extract_day + , subq_1.ds_partitioned__extract_dow AS ds_partitioned__extract_dow + , subq_1.ds_partitioned__extract_doy AS ds_partitioned__extract_doy + , subq_1.paid_at__day AS paid_at__day + , subq_1.paid_at__week AS paid_at__week + , subq_1.paid_at__month AS paid_at__month + , subq_1.paid_at__quarter AS paid_at__quarter + , subq_1.paid_at__year AS paid_at__year + , subq_1.paid_at__extract_year AS paid_at__extract_year + , subq_1.paid_at__extract_quarter AS paid_at__extract_quarter + , subq_1.paid_at__extract_month AS paid_at__extract_month + , subq_1.paid_at__extract_day AS paid_at__extract_day + , subq_1.paid_at__extract_dow AS paid_at__extract_dow + , subq_1.paid_at__extract_doy AS paid_at__extract_doy + , subq_1.booking__ds__day AS booking__ds__day + , subq_1.booking__ds__week AS booking__ds__week + , subq_1.booking__ds__month AS booking__ds__month + , subq_1.booking__ds__quarter AS booking__ds__quarter + , subq_1.booking__ds__year AS booking__ds__year + , subq_1.booking__ds__extract_year AS booking__ds__extract_year + , subq_1.booking__ds__extract_quarter AS booking__ds__extract_quarter + , subq_1.booking__ds__extract_month AS booking__ds__extract_month + , subq_1.booking__ds__extract_day AS booking__ds__extract_day + , subq_1.booking__ds__extract_dow AS booking__ds__extract_dow + , subq_1.booking__ds__extract_doy AS booking__ds__extract_doy + , subq_1.booking__ds_partitioned__day AS booking__ds_partitioned__day + , subq_1.booking__ds_partitioned__week AS booking__ds_partitioned__week + , subq_1.booking__ds_partitioned__month AS booking__ds_partitioned__month + , subq_1.booking__ds_partitioned__quarter AS booking__ds_partitioned__quarter + , subq_1.booking__ds_partitioned__year AS booking__ds_partitioned__year + , subq_1.booking__ds_partitioned__extract_year AS booking__ds_partitioned__extract_year + , subq_1.booking__ds_partitioned__extract_quarter AS booking__ds_partitioned__extract_quarter + , subq_1.booking__ds_partitioned__extract_month AS booking__ds_partitioned__extract_month + , subq_1.booking__ds_partitioned__extract_day AS booking__ds_partitioned__extract_day + , subq_1.booking__ds_partitioned__extract_dow AS booking__ds_partitioned__extract_dow + , subq_1.booking__ds_partitioned__extract_doy AS booking__ds_partitioned__extract_doy + , subq_1.booking__paid_at__day AS booking__paid_at__day + , subq_1.booking__paid_at__week AS booking__paid_at__week + , subq_1.booking__paid_at__month AS booking__paid_at__month + , subq_1.booking__paid_at__quarter AS booking__paid_at__quarter + , subq_1.booking__paid_at__year AS booking__paid_at__year + , subq_1.booking__paid_at__extract_year AS booking__paid_at__extract_year + , subq_1.booking__paid_at__extract_quarter AS booking__paid_at__extract_quarter + , subq_1.booking__paid_at__extract_month AS booking__paid_at__extract_month + , subq_1.booking__paid_at__extract_day AS booking__paid_at__extract_day + , subq_1.booking__paid_at__extract_dow AS booking__paid_at__extract_dow + , subq_1.booking__paid_at__extract_doy AS booking__paid_at__extract_doy + , subq_1.listing AS listing + , subq_1.guest AS guest + , subq_1.host AS host + , subq_1.booking__listing AS booking__listing + , subq_1.booking__guest AS booking__guest + , subq_1.booking__host AS booking__host + , subq_1.is_instant AS is_instant + , subq_1.booking__is_instant AS booking__is_instant + , subq_1.bookings AS bookings + , subq_1.instant_bookings AS instant_bookings + , subq_1.booking_value AS booking_value + , subq_1.max_booking_value AS max_booking_value + , subq_1.min_booking_value AS min_booking_value + , subq_1.bookers AS bookers + , subq_1.average_booking_value AS average_booking_value + , subq_1.referred_bookings AS referred_bookings + , subq_1.median_booking_value AS median_booking_value + , subq_1.booking_value_p99 AS booking_value_p99 + , subq_1.discrete_booking_value_p99 AS discrete_booking_value_p99 + , subq_1.approximate_continuous_booking_value_p99 AS approximate_continuous_booking_value_p99 + , subq_1.approximate_discrete_booking_value_p99 AS approximate_discrete_booking_value_p99 FROM ( - -- Read Elements From Semantic Model 'bookings_source' + -- Time Spine SELECT - 1 AS bookings - , CASE WHEN is_instant THEN 1 ELSE 0 END AS instant_bookings - , bookings_source_src_28000.booking_value - , bookings_source_src_28000.booking_value AS max_booking_value - , bookings_source_src_28000.booking_value AS min_booking_value - , bookings_source_src_28000.guest_id AS bookers - , bookings_source_src_28000.booking_value AS average_booking_value - , bookings_source_src_28000.booking_value AS booking_payments - , CASE WHEN referrer_id IS NOT NULL THEN 1 ELSE 0 END AS referred_bookings - , bookings_source_src_28000.booking_value AS median_booking_value - , bookings_source_src_28000.booking_value AS booking_value_p99 - , bookings_source_src_28000.booking_value AS discrete_booking_value_p99 - , bookings_source_src_28000.booking_value AS approximate_continuous_booking_value_p99 - , bookings_source_src_28000.booking_value AS approximate_discrete_booking_value_p99 - , bookings_source_src_28000.is_instant - , DATE_TRUNC('day', bookings_source_src_28000.ds) AS ds__day - , DATE_TRUNC('week', bookings_source_src_28000.ds) AS ds__week - , DATE_TRUNC('month', bookings_source_src_28000.ds) AS ds__month - , DATE_TRUNC('quarter', bookings_source_src_28000.ds) AS ds__quarter - , DATE_TRUNC('year', bookings_source_src_28000.ds) AS ds__year - , EXTRACT(year FROM bookings_source_src_28000.ds) AS ds__extract_year - , EXTRACT(quarter FROM bookings_source_src_28000.ds) AS ds__extract_quarter - , EXTRACT(month FROM bookings_source_src_28000.ds) AS ds__extract_month - , EXTRACT(day FROM bookings_source_src_28000.ds) AS ds__extract_day - , EXTRACT(isodow FROM bookings_source_src_28000.ds) AS ds__extract_dow - , EXTRACT(doy FROM bookings_source_src_28000.ds) AS ds__extract_doy - , DATE_TRUNC('day', bookings_source_src_28000.ds_partitioned) AS ds_partitioned__day - , DATE_TRUNC('week', bookings_source_src_28000.ds_partitioned) AS ds_partitioned__week - , DATE_TRUNC('month', bookings_source_src_28000.ds_partitioned) AS ds_partitioned__month - , DATE_TRUNC('quarter', bookings_source_src_28000.ds_partitioned) AS ds_partitioned__quarter - , DATE_TRUNC('year', bookings_source_src_28000.ds_partitioned) AS ds_partitioned__year - , EXTRACT(year FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_year - , EXTRACT(quarter FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_quarter - , EXTRACT(month FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_month - , EXTRACT(day FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_day - , EXTRACT(isodow FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_dow - , EXTRACT(doy FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_doy - , DATE_TRUNC('day', bookings_source_src_28000.paid_at) AS paid_at__day - , DATE_TRUNC('week', bookings_source_src_28000.paid_at) AS paid_at__week - , DATE_TRUNC('month', bookings_source_src_28000.paid_at) AS paid_at__month - , DATE_TRUNC('quarter', bookings_source_src_28000.paid_at) AS paid_at__quarter - , DATE_TRUNC('year', bookings_source_src_28000.paid_at) AS paid_at__year - , EXTRACT(year FROM bookings_source_src_28000.paid_at) AS paid_at__extract_year - , EXTRACT(quarter FROM bookings_source_src_28000.paid_at) AS paid_at__extract_quarter - , EXTRACT(month FROM bookings_source_src_28000.paid_at) AS paid_at__extract_month - , EXTRACT(day FROM bookings_source_src_28000.paid_at) AS paid_at__extract_day - , EXTRACT(isodow FROM bookings_source_src_28000.paid_at) AS paid_at__extract_dow - , EXTRACT(doy FROM bookings_source_src_28000.paid_at) AS paid_at__extract_doy - , bookings_source_src_28000.is_instant AS booking__is_instant - , DATE_TRUNC('day', bookings_source_src_28000.ds) AS booking__ds__day - , DATE_TRUNC('week', bookings_source_src_28000.ds) AS booking__ds__week - , DATE_TRUNC('month', bookings_source_src_28000.ds) AS booking__ds__month - , DATE_TRUNC('quarter', bookings_source_src_28000.ds) AS booking__ds__quarter - , DATE_TRUNC('year', bookings_source_src_28000.ds) AS booking__ds__year - , EXTRACT(year FROM bookings_source_src_28000.ds) AS booking__ds__extract_year - , EXTRACT(quarter FROM bookings_source_src_28000.ds) AS booking__ds__extract_quarter - , EXTRACT(month FROM bookings_source_src_28000.ds) AS booking__ds__extract_month - , EXTRACT(day FROM bookings_source_src_28000.ds) AS booking__ds__extract_day - , EXTRACT(isodow FROM bookings_source_src_28000.ds) AS booking__ds__extract_dow - , EXTRACT(doy FROM bookings_source_src_28000.ds) AS booking__ds__extract_doy - , DATE_TRUNC('day', bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__day - , DATE_TRUNC('week', bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__week - , DATE_TRUNC('month', bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__month - , DATE_TRUNC('quarter', bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__quarter - , DATE_TRUNC('year', bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__year - , EXTRACT(year FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_year - , EXTRACT(quarter FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_quarter - , EXTRACT(month FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_month - , EXTRACT(day FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_day - , EXTRACT(isodow FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_dow - , EXTRACT(doy FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_doy - , DATE_TRUNC('day', bookings_source_src_28000.paid_at) AS booking__paid_at__day - , DATE_TRUNC('week', bookings_source_src_28000.paid_at) AS booking__paid_at__week - , DATE_TRUNC('month', bookings_source_src_28000.paid_at) AS booking__paid_at__month - , DATE_TRUNC('quarter', bookings_source_src_28000.paid_at) AS booking__paid_at__quarter - , DATE_TRUNC('year', bookings_source_src_28000.paid_at) AS booking__paid_at__year - , EXTRACT(year FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_year - , EXTRACT(quarter FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_quarter - , EXTRACT(month FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_month - , EXTRACT(day FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_day - , EXTRACT(isodow FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_dow - , EXTRACT(doy FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_doy - , bookings_source_src_28000.listing_id AS listing - , bookings_source_src_28000.guest_id AS guest - , bookings_source_src_28000.host_id AS host - , bookings_source_src_28000.listing_id AS booking__listing - , bookings_source_src_28000.guest_id AS booking__guest - , bookings_source_src_28000.host_id AS booking__host - FROM ***************************.fct_bookings bookings_source_src_28000 - ) subq_0 - ) subq_1 - ON - subq_2.metric_time__day - INTERVAL 5 day = subq_1.metric_time__day - ) subq_4 - ) subq_5 + subq_3.ds AS metric_time__day + FROM ***************************.mf_time_spine subq_3 + ) subq_2 + INNER JOIN ( + -- Metric Time Dimension 'ds' + SELECT + subq_0.ds__day + , subq_0.ds__week + , subq_0.ds__month + , subq_0.ds__quarter + , subq_0.ds__year + , subq_0.ds__extract_year + , subq_0.ds__extract_quarter + , subq_0.ds__extract_month + , subq_0.ds__extract_day + , subq_0.ds__extract_dow + , subq_0.ds__extract_doy + , subq_0.ds_partitioned__day + , subq_0.ds_partitioned__week + , subq_0.ds_partitioned__month + , subq_0.ds_partitioned__quarter + , subq_0.ds_partitioned__year + , subq_0.ds_partitioned__extract_year + , subq_0.ds_partitioned__extract_quarter + , subq_0.ds_partitioned__extract_month + , subq_0.ds_partitioned__extract_day + , subq_0.ds_partitioned__extract_dow + , subq_0.ds_partitioned__extract_doy + , subq_0.paid_at__day + , subq_0.paid_at__week + , subq_0.paid_at__month + , subq_0.paid_at__quarter + , subq_0.paid_at__year + , subq_0.paid_at__extract_year + , subq_0.paid_at__extract_quarter + , subq_0.paid_at__extract_month + , subq_0.paid_at__extract_day + , subq_0.paid_at__extract_dow + , subq_0.paid_at__extract_doy + , subq_0.booking__ds__day + , subq_0.booking__ds__week + , subq_0.booking__ds__month + , subq_0.booking__ds__quarter + , subq_0.booking__ds__year + , subq_0.booking__ds__extract_year + , subq_0.booking__ds__extract_quarter + , subq_0.booking__ds__extract_month + , subq_0.booking__ds__extract_day + , subq_0.booking__ds__extract_dow + , subq_0.booking__ds__extract_doy + , subq_0.booking__ds_partitioned__day + , subq_0.booking__ds_partitioned__week + , subq_0.booking__ds_partitioned__month + , subq_0.booking__ds_partitioned__quarter + , subq_0.booking__ds_partitioned__year + , subq_0.booking__ds_partitioned__extract_year + , subq_0.booking__ds_partitioned__extract_quarter + , subq_0.booking__ds_partitioned__extract_month + , subq_0.booking__ds_partitioned__extract_day + , subq_0.booking__ds_partitioned__extract_dow + , subq_0.booking__ds_partitioned__extract_doy + , subq_0.booking__paid_at__day + , subq_0.booking__paid_at__week + , subq_0.booking__paid_at__month + , subq_0.booking__paid_at__quarter + , subq_0.booking__paid_at__year + , subq_0.booking__paid_at__extract_year + , subq_0.booking__paid_at__extract_quarter + , subq_0.booking__paid_at__extract_month + , subq_0.booking__paid_at__extract_day + , subq_0.booking__paid_at__extract_dow + , subq_0.booking__paid_at__extract_doy + , subq_0.ds__day AS metric_time__day + , subq_0.ds__week AS metric_time__week + , subq_0.ds__month AS metric_time__month + , subq_0.ds__quarter AS metric_time__quarter + , subq_0.ds__year AS metric_time__year + , subq_0.ds__extract_year AS metric_time__extract_year + , subq_0.ds__extract_quarter AS metric_time__extract_quarter + , subq_0.ds__extract_month AS metric_time__extract_month + , subq_0.ds__extract_day AS metric_time__extract_day + , subq_0.ds__extract_dow AS metric_time__extract_dow + , subq_0.ds__extract_doy AS metric_time__extract_doy + , subq_0.listing + , subq_0.guest + , subq_0.host + , subq_0.booking__listing + , subq_0.booking__guest + , subq_0.booking__host + , subq_0.is_instant + , subq_0.booking__is_instant + , subq_0.bookings + , subq_0.instant_bookings + , subq_0.booking_value + , subq_0.max_booking_value + , subq_0.min_booking_value + , subq_0.bookers + , subq_0.average_booking_value + , subq_0.referred_bookings + , subq_0.median_booking_value + , subq_0.booking_value_p99 + , subq_0.discrete_booking_value_p99 + , subq_0.approximate_continuous_booking_value_p99 + , subq_0.approximate_discrete_booking_value_p99 + FROM ( + -- Read Elements From Semantic Model 'bookings_source' + SELECT + 1 AS bookings + , CASE WHEN is_instant THEN 1 ELSE 0 END AS instant_bookings + , bookings_source_src_28000.booking_value + , bookings_source_src_28000.booking_value AS max_booking_value + , bookings_source_src_28000.booking_value AS min_booking_value + , bookings_source_src_28000.guest_id AS bookers + , bookings_source_src_28000.booking_value AS average_booking_value + , bookings_source_src_28000.booking_value AS booking_payments + , CASE WHEN referrer_id IS NOT NULL THEN 1 ELSE 0 END AS referred_bookings + , bookings_source_src_28000.booking_value AS median_booking_value + , bookings_source_src_28000.booking_value AS booking_value_p99 + , bookings_source_src_28000.booking_value AS discrete_booking_value_p99 + , bookings_source_src_28000.booking_value AS approximate_continuous_booking_value_p99 + , bookings_source_src_28000.booking_value AS approximate_discrete_booking_value_p99 + , bookings_source_src_28000.is_instant + , DATE_TRUNC('day', bookings_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', bookings_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', bookings_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', bookings_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', bookings_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM bookings_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM bookings_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM bookings_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM bookings_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM bookings_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM bookings_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', bookings_source_src_28000.ds_partitioned) AS ds_partitioned__day + , DATE_TRUNC('week', bookings_source_src_28000.ds_partitioned) AS ds_partitioned__week + , DATE_TRUNC('month', bookings_source_src_28000.ds_partitioned) AS ds_partitioned__month + , DATE_TRUNC('quarter', bookings_source_src_28000.ds_partitioned) AS ds_partitioned__quarter + , DATE_TRUNC('year', bookings_source_src_28000.ds_partitioned) AS ds_partitioned__year + , EXTRACT(year FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_year + , EXTRACT(quarter FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_quarter + , EXTRACT(month FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_month + , EXTRACT(day FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_day + , EXTRACT(isodow FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_dow + , EXTRACT(doy FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_doy + , DATE_TRUNC('day', bookings_source_src_28000.paid_at) AS paid_at__day + , DATE_TRUNC('week', bookings_source_src_28000.paid_at) AS paid_at__week + , DATE_TRUNC('month', bookings_source_src_28000.paid_at) AS paid_at__month + , DATE_TRUNC('quarter', bookings_source_src_28000.paid_at) AS paid_at__quarter + , DATE_TRUNC('year', bookings_source_src_28000.paid_at) AS paid_at__year + , EXTRACT(year FROM bookings_source_src_28000.paid_at) AS paid_at__extract_year + , EXTRACT(quarter FROM bookings_source_src_28000.paid_at) AS paid_at__extract_quarter + , EXTRACT(month FROM bookings_source_src_28000.paid_at) AS paid_at__extract_month + , EXTRACT(day FROM bookings_source_src_28000.paid_at) AS paid_at__extract_day + , EXTRACT(isodow FROM bookings_source_src_28000.paid_at) AS paid_at__extract_dow + , EXTRACT(doy FROM bookings_source_src_28000.paid_at) AS paid_at__extract_doy + , bookings_source_src_28000.is_instant AS booking__is_instant + , DATE_TRUNC('day', bookings_source_src_28000.ds) AS booking__ds__day + , DATE_TRUNC('week', bookings_source_src_28000.ds) AS booking__ds__week + , DATE_TRUNC('month', bookings_source_src_28000.ds) AS booking__ds__month + , DATE_TRUNC('quarter', bookings_source_src_28000.ds) AS booking__ds__quarter + , DATE_TRUNC('year', bookings_source_src_28000.ds) AS booking__ds__year + , EXTRACT(year FROM bookings_source_src_28000.ds) AS booking__ds__extract_year + , EXTRACT(quarter FROM bookings_source_src_28000.ds) AS booking__ds__extract_quarter + , EXTRACT(month FROM bookings_source_src_28000.ds) AS booking__ds__extract_month + , EXTRACT(day FROM bookings_source_src_28000.ds) AS booking__ds__extract_day + , EXTRACT(isodow FROM bookings_source_src_28000.ds) AS booking__ds__extract_dow + , EXTRACT(doy FROM bookings_source_src_28000.ds) AS booking__ds__extract_doy + , DATE_TRUNC('day', bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__day + , DATE_TRUNC('week', bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__week + , DATE_TRUNC('month', bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__month + , DATE_TRUNC('quarter', bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__quarter + , DATE_TRUNC('year', bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__year + , EXTRACT(year FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_year + , EXTRACT(quarter FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_quarter + , EXTRACT(month FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_month + , EXTRACT(day FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_day + , EXTRACT(isodow FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_dow + , EXTRACT(doy FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_doy + , DATE_TRUNC('day', bookings_source_src_28000.paid_at) AS booking__paid_at__day + , DATE_TRUNC('week', bookings_source_src_28000.paid_at) AS booking__paid_at__week + , DATE_TRUNC('month', bookings_source_src_28000.paid_at) AS booking__paid_at__month + , DATE_TRUNC('quarter', bookings_source_src_28000.paid_at) AS booking__paid_at__quarter + , DATE_TRUNC('year', bookings_source_src_28000.paid_at) AS booking__paid_at__year + , EXTRACT(year FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_year + , EXTRACT(quarter FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_quarter + , EXTRACT(month FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_month + , EXTRACT(day FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_day + , EXTRACT(isodow FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_dow + , EXTRACT(doy FROM bookings_source_src_28000.paid_at) AS booking__paid_at__extract_doy + , bookings_source_src_28000.listing_id AS listing + , bookings_source_src_28000.guest_id AS guest + , bookings_source_src_28000.host_id AS host + , bookings_source_src_28000.listing_id AS booking__listing + , bookings_source_src_28000.guest_id AS booking__guest + , bookings_source_src_28000.host_id AS booking__host + FROM ***************************.fct_bookings bookings_source_src_28000 + ) subq_0 + ) subq_1 + ON + subq_2.metric_time__day - INTERVAL 5 day = subq_1.metric_time__day + ) subq_4 + WHERE listing IS NOT NULL + ) subq_5 + ) subq_6 GROUP BY - subq_5.metric_time__day - , subq_5.booking__is_instant - ) subq_6 - ) subq_7 - ) subq_8 + subq_6.metric_time__day + ) subq_7 + ) subq_8 + ) subq_9 ON - subq_9.metric_time__day - INTERVAL 2 day = subq_8.metric_time__day - ) subq_11 + subq_10.metric_time__day - INTERVAL 2 day = subq_9.metric_time__day + ) subq_12 WHERE booking__is_instant - ) subq_12 -) subq_13 + ) subq_13 +) subq_14 diff --git a/tests_metricflow/snapshots/test_derived_metric_rendering.py/SqlQueryPlan/DuckDB/test_nested_derived_metric_offset_with_joined_where_constraint_not_selected__plan0_optimized.sql b/tests_metricflow/snapshots/test_derived_metric_rendering.py/SqlQueryPlan/DuckDB/test_nested_derived_metric_offset_with_joined_where_constraint_not_selected__plan0_optimized.sql index d62752cb4..ef396c152 100644 --- a/tests_metricflow/snapshots/test_derived_metric_rendering.py/SqlQueryPlan/DuckDB/test_nested_derived_metric_offset_with_joined_where_constraint_not_selected__plan0_optimized.sql +++ b/tests_metricflow/snapshots/test_derived_metric_rendering.py/SqlQueryPlan/DuckDB/test_nested_derived_metric_offset_with_joined_where_constraint_not_selected__plan0_optimized.sql @@ -15,44 +15,52 @@ FROM ( FROM ( -- Join to Time Spine Dataset SELECT - subq_24.ds AS metric_time__day - , subq_22.booking__is_instant AS booking__is_instant - , subq_22.bookings_offset_once AS bookings_offset_once - FROM ***************************.mf_time_spine subq_24 + subq_26.ds AS metric_time__day + , subq_24.bookings_offset_once AS bookings_offset_once + FROM ***************************.mf_time_spine subq_26 INNER JOIN ( -- Compute Metrics via Expressions SELECT metric_time__day - , booking__is_instant , 2 * bookings AS bookings_offset_once FROM ( - -- Join to Time Spine Dataset - -- Pass Only Elements: ['bookings', 'booking__is_instant', 'metric_time__day'] + -- Constrain Output with WHERE + -- Pass Only Elements: ['bookings', 'metric_time__day'] -- Aggregate Measures -- Compute Metrics via Expressions SELECT - subq_17.ds AS metric_time__day - , subq_15.booking__is_instant AS booking__is_instant - , SUM(subq_15.bookings) AS bookings - FROM ***************************.mf_time_spine subq_17 - INNER JOIN ( - -- Read Elements From Semantic Model 'bookings_source' - -- Metric Time Dimension 'ds' + metric_time__day + , SUM(bookings) AS bookings + FROM ( + -- Join to Time Spine Dataset SELECT - DATE_TRUNC('day', ds) AS metric_time__day - , is_instant AS booking__is_instant - , 1 AS bookings - FROM ***************************.fct_bookings bookings_source_src_28000 - ) subq_15 - ON - subq_17.ds - INTERVAL 5 day = subq_15.metric_time__day + subq_18.ds AS metric_time__day + , subq_16.listing AS listing + , subq_16.bookings AS bookings + FROM ***************************.mf_time_spine subq_18 + INNER JOIN ( + -- Read Elements From Semantic Model 'bookings_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , listing_id AS listing + , 1 AS bookings + FROM ***************************.fct_bookings bookings_source_src_28000 + ) subq_16 + ON + subq_18.ds - INTERVAL 5 day = subq_16.metric_time__day + ) subq_19 + -- this looks fine + WHERE listing IS NOT NULL GROUP BY - subq_17.ds - , subq_15.booking__is_instant - ) subq_21 - ) subq_22 + metric_time__day + ) subq_23 + ) subq_24 ON - subq_24.ds - INTERVAL 2 day = subq_22.metric_time__day - ) subq_25 + subq_26.ds - INTERVAL 2 day = subq_24.metric_time__day + ) subq_27 + -- this is not fine. should be pushed down. exception: if it's offset and the filter is on metric_time/agg_time (is agg time supported for offsets?) + -- update this test accordingly + -- we need to use the same logic we're using for join_to_timespine here, I think. this is limited by using a list of filters instead of one AND filter WHERE booking__is_instant -) subq_27 +) subq_29