diff --git a/tests_metricflow/query_rendering/test_cumulative_metric_rendering.py b/tests_metricflow/query_rendering/test_cumulative_metric_rendering.py index 17c1fd6d7f..c5a09e4aa4 100644 --- a/tests_metricflow/query_rendering/test_cumulative_metric_rendering.py +++ b/tests_metricflow/query_rendering/test_cumulative_metric_rendering.py @@ -16,7 +16,13 @@ from metricflow_semantics.specs.query_spec import MetricFlowQuerySpec from metricflow_semantics.specs.spec_classes import EntityReference, MetricSpec, TimeDimensionSpec from metricflow_semantics.test_helpers.config_helpers import MetricFlowTestConfiguration -from metricflow_semantics.test_helpers.metric_time_dimension import MTD_SPEC_DAY, MTD_SPEC_MONTH +from metricflow_semantics.test_helpers.metric_time_dimension import ( + MTD_SPEC_DAY, + MTD_SPEC_MONTH, + MTD_SPEC_WEEK, + MTD_SPEC_QUARTER, + MTD_SPEC_YEAR, +) from metricflow.dataflow.builder.dataflow_plan_builder import DataflowPlanBuilder from metricflow.plan_conversion.dataflow_to_sql import DataflowToSqlQueryPlanConverter @@ -38,7 +44,6 @@ def test_cumulative_metric( dataflow_plan = dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="trailing_2_months_revenue"),), - dimension_specs=(), time_dimension_specs=( TimeDimensionSpec( element_name="ds", @@ -76,7 +81,6 @@ def test_cumulative_metric_with_time_constraint( dataflow_plan = dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="trailing_2_months_revenue"),), - dimension_specs=(), time_dimension_specs=( TimeDimensionSpec( element_name="metric_time", @@ -150,7 +154,6 @@ def test_cumulative_metric_no_ds( dataflow_plan = dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="trailing_2_months_revenue"),), - dimension_specs=(), time_dimension_specs=(), ) ) @@ -177,7 +180,6 @@ def test_cumulative_metric_no_window( dataflow_plan = dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="revenue_all_time"),), - dimension_specs=(), time_dimension_specs=( TimeDimensionSpec( element_name="ds", @@ -210,7 +212,6 @@ def test_cumulative_metric_no_window_with_time_constraint( dataflow_plan = dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="revenue_all_time"),), - dimension_specs=(), time_dimension_specs=(MTD_SPEC_DAY,), time_range_constraint=TimeRangeConstraint( start_time=as_datetime("2020-01-01"), end_time=as_datetime("2020-01-01") @@ -240,7 +241,6 @@ def test_cumulative_metric_grain_to_date( dataflow_plan = dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="revenue_mtd"),), - dimension_specs=(), time_dimension_specs=( TimeDimensionSpec( element_name="ds", @@ -273,7 +273,6 @@ def test_cumulative_metric_month( dataflow_plan = extended_date_dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="trailing_3_months_bookings"),), - dimension_specs=(), time_dimension_specs=(MTD_SPEC_MONTH,), time_range_constraint=TimeRangeConstraint( start_time=as_datetime("2020-03-05"), end_time=as_datetime("2021-01-04") @@ -303,7 +302,6 @@ def test_cumulative_metric_with_agg_time_dimension( dataflow_plan = dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="trailing_2_months_revenue"),), - dimension_specs=(), time_dimension_specs=( TimeDimensionSpec(element_name="ds", entity_links=(EntityReference("revenue_instance"),)), ), @@ -332,7 +330,6 @@ def test_cumulative_metric_with_multiple_agg_time_dimensions( dataflow_plan = dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="trailing_2_months_revenue"),), - dimension_specs=(), time_dimension_specs=( TimeDimensionSpec( element_name="ds", @@ -370,7 +367,6 @@ def test_cumulative_metric_with_multiple_metric_time_dimensions( dataflow_plan = dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="trailing_2_months_revenue"),), - dimension_specs=(), time_dimension_specs=(MTD_SPEC_DAY, MTD_SPEC_MONTH), ) ) @@ -397,7 +393,6 @@ def test_cumulative_metric_with_agg_time_and_metric_time( dataflow_plan = dataflow_plan_builder.build_plan( MetricFlowQuerySpec( metric_specs=(MetricSpec(element_name="trailing_2_months_revenue"),), - dimension_specs=(), time_dimension_specs=( MTD_SPEC_DAY, TimeDimensionSpec( @@ -416,3 +411,222 @@ def test_cumulative_metric_with_agg_time_and_metric_time( sql_client=sql_client, node=dataflow_plan.sink_node, ) + + +@pytest.mark.sql_engine_snapshot +def test_cumulative_metric_with_non_default_grain( + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + mf_engine_test_fixture_mapping: Mapping[SemanticManifestSetup, MetricFlowEngineTestFixture], + sql_client: SqlClient, +) -> None: + """Tests rendering a query for a cumulative all-time metric queried with non-default grain.""" + dataflow_plan = dataflow_plan_builder.build_plan( + MetricFlowQuerySpec( + metric_specs=(MetricSpec(element_name="revenue_all_time"),), + time_dimension_specs=(MTD_SPEC_WEEK,), + ) + ) + + convert_and_check( + request=request, + mf_test_configuration=mf_test_configuration, + dataflow_to_sql_converter=dataflow_to_sql_converter, + sql_client=sql_client, + node=dataflow_plan.sink_node, + ) + + +@pytest.mark.sql_engine_snapshot +def test_window_metric_with_non_default_grain( + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + mf_engine_test_fixture_mapping: Mapping[SemanticManifestSetup, MetricFlowEngineTestFixture], + sql_client: SqlClient, +) -> None: + """Tests rendering a query for a cumulative window metric queried with non-default grain.""" + dataflow_plan = dataflow_plan_builder.build_plan( + MetricFlowQuerySpec( + metric_specs=(MetricSpec(element_name="trailing_2_months_revenue"),), + time_dimension_specs=(MTD_SPEC_YEAR,), + ) + ) + + convert_and_check( + request=request, + mf_test_configuration=mf_test_configuration, + dataflow_to_sql_converter=dataflow_to_sql_converter, + sql_client=sql_client, + node=dataflow_plan.sink_node, + ) + + +@pytest.mark.sql_engine_snapshot +def test_grain_to_date_metric_with_non_default_grain( + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + mf_engine_test_fixture_mapping: Mapping[SemanticManifestSetup, MetricFlowEngineTestFixture], + sql_client: SqlClient, +) -> None: + """Tests rendering a query for a cumulative grain to date metric queried with non-default grain.""" + dataflow_plan = dataflow_plan_builder.build_plan( + MetricFlowQuerySpec( + metric_specs=(MetricSpec(element_name="revenue_mtd"),), + time_dimension_specs=(MTD_SPEC_MONTH,), + ) + ) + + convert_and_check( + request=request, + mf_test_configuration=mf_test_configuration, + dataflow_to_sql_converter=dataflow_to_sql_converter, + sql_client=sql_client, + node=dataflow_plan.sink_node, + ) + + +@pytest.mark.sql_engine_snapshot +def test_window_metric_with_multiple_grains( + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + mf_engine_test_fixture_mapping: Mapping[SemanticManifestSetup, MetricFlowEngineTestFixture], + sql_client: SqlClient, +) -> None: + """Tests rendering a query for a cumulative window metric queried with multiple grains. + + Uses both metric_time and agg_time_dimension. Includes default grain. + """ + dataflow_plan = dataflow_plan_builder.build_plan( + MetricFlowQuerySpec( + metric_specs=(MetricSpec(element_name="every_two_days_bookers_fill_nulls_with_0"),), + time_dimension_specs=( + MTD_SPEC_DAY, + TimeDimensionSpec( + element_name="ds", + entity_links=(EntityReference("booking"),), + time_granularity=TimeGranularity.MONTH, + ), + ), + ) + ) + + convert_and_check( + request=request, + mf_test_configuration=mf_test_configuration, + dataflow_to_sql_converter=dataflow_to_sql_converter, + sql_client=sql_client, + node=dataflow_plan.sink_node, + ) + + +@pytest.mark.sql_engine_snapshot +def test_grain_to_date_metric_with_multiple_grains( + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + mf_engine_test_fixture_mapping: Mapping[SemanticManifestSetup, MetricFlowEngineTestFixture], + sql_client: SqlClient, +) -> None: + """Tests rendering a query for a cumulative grain to date metric queried with multiple grains. + + Uses agg time dimension instead of metric_time. Excludes default grain. + """ + dataflow_plan = dataflow_plan_builder.build_plan( + MetricFlowQuerySpec( + metric_specs=(MetricSpec(element_name="revenue_mtd"),), + time_dimension_specs=( + TimeDimensionSpec( + element_name="ds", + entity_links=(EntityReference("revenue_instance"),), + time_granularity=TimeGranularity.QUARTER, + ), + TimeDimensionSpec( + element_name="ds", + entity_links=(EntityReference("revenue_instance"),), + time_granularity=TimeGranularity.YEAR, + ), + ), + ) + ) + + convert_and_check( + request=request, + mf_test_configuration=mf_test_configuration, + dataflow_to_sql_converter=dataflow_to_sql_converter, + sql_client=sql_client, + node=dataflow_plan.sink_node, + ) + + +@pytest.mark.sql_engine_snapshot +def test_all_time_metric_with_multiple_grains( + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + mf_engine_test_fixture_mapping: Mapping[SemanticManifestSetup, MetricFlowEngineTestFixture], + sql_client: SqlClient, +) -> None: + """Tests rendering a query for a cumulative all-time metric queried with non-default grain. + + Uses only metric_time. Excludes default grain. + """ + dataflow_plan = dataflow_plan_builder.build_plan( + MetricFlowQuerySpec( + metric_specs=(MetricSpec(element_name="revenue_mtd"),), + time_dimension_specs=(MTD_SPEC_WEEK, MTD_SPEC_QUARTER), + ) + ) + + convert_and_check( + request=request, + mf_test_configuration=mf_test_configuration, + dataflow_to_sql_converter=dataflow_to_sql_converter, + sql_client=sql_client, + node=dataflow_plan.sink_node, + ) + + +@pytest.mark.sql_engine_snapshot +def test_derived_cumulative_metric_with_non_default_grain( + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + mf_engine_test_fixture_mapping: Mapping[SemanticManifestSetup, MetricFlowEngineTestFixture], + sql_client: SqlClient, +) -> None: + """Test querying a derived metric with a cumulative input metric using non-default granularity.""" + dataflow_plan = dataflow_plan_builder.build_plan( + MetricFlowQuerySpec( + metric_specs=(MetricSpec(element_name="trailing_2_months_revenue_sub_10"),), + time_dimension_specs=(MTD_SPEC_WEEK,), + ) + ) + + convert_and_check( + request=request, + mf_test_configuration=mf_test_configuration, + dataflow_to_sql_converter=dataflow_to_sql_converter, + sql_client=sql_client, + node=dataflow_plan.sink_node, + ) + + +# Query 2 cumulative metrics with different agg_time_dimensions - what will happen?? + +# TODO: write the following tests when unblocked +# - Render each of the allowed period_aggs (both set in YAML & default) +# - Query cumulative metric with non-day default_grain (using default grain and non-default grain) +# - Query 2 metrics with different default_grains using metric_time (no grain specified) +# - If default grain is WEEK, query with a higher grain (check that we still get correct values) +# - Query cumulative metric with sub-daily grain diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_all_time_metric_with_multiple_grains__plan0.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_all_time_metric_with_multiple_grains__plan0.sql new file mode 100644 index 0000000000..6f3497dd6c --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_all_time_metric_with_multiple_grains__plan0.sql @@ -0,0 +1,177 @@ +-- Re-aggregate Metrics via Window Functions +SELECT + subq_8.metric_time__week + , subq_8.metric_time__quarter + , subq_8.revenue_mtd +FROM ( + SELECT + subq_7.metric_time__week + , subq_7.metric_time__quarter + , FIRST_VALUE(subq_7.revenue_mtd) OVER ( + PARTITION BY + subq_7.metric_time__week + , subq_7.metric_time__quarter + ORDER BY subq_7.metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS revenue_mtd + FROM ( + -- Compute Metrics via Expressions + SELECT + subq_6.metric_time__day + , subq_6.metric_time__week + , subq_6.metric_time__quarter + , subq_6.txn_revenue AS revenue_mtd + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__day + , subq_5.metric_time__week + , subq_5.metric_time__quarter + , SUM(subq_5.txn_revenue) AS txn_revenue + FROM ( + -- Pass Only Elements: ['txn_revenue', 'metric_time__week', 'metric_time__quarter', 'metric_time__day'] + SELECT + subq_4.metric_time__day + , subq_4.metric_time__week + , subq_4.metric_time__quarter + , subq_4.txn_revenue + FROM ( + -- Join Self Over Time Range + SELECT + subq_2.metric_time__day AS metric_time__day + , subq_2.metric_time__week AS metric_time__week + , subq_2.metric_time__quarter AS metric_time__quarter + , 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.revenue_instance__ds__day AS revenue_instance__ds__day + , subq_1.revenue_instance__ds__week AS revenue_instance__ds__week + , subq_1.revenue_instance__ds__month AS revenue_instance__ds__month + , subq_1.revenue_instance__ds__quarter AS revenue_instance__ds__quarter + , subq_1.revenue_instance__ds__year AS revenue_instance__ds__year + , subq_1.revenue_instance__ds__extract_year AS revenue_instance__ds__extract_year + , subq_1.revenue_instance__ds__extract_quarter AS revenue_instance__ds__extract_quarter + , subq_1.revenue_instance__ds__extract_month AS revenue_instance__ds__extract_month + , subq_1.revenue_instance__ds__extract_day AS revenue_instance__ds__extract_day + , subq_1.revenue_instance__ds__extract_dow AS revenue_instance__ds__extract_dow + , subq_1.revenue_instance__ds__extract_doy AS revenue_instance__ds__extract_doy + , subq_1.metric_time__month AS metric_time__month + , subq_1.metric_time__year AS metric_time__year + , subq_1.metric_time__extract_year AS metric_time__extract_year + , subq_1.metric_time__extract_quarter AS metric_time__extract_quarter + , subq_1.metric_time__extract_month AS metric_time__extract_month + , subq_1.metric_time__extract_day AS metric_time__extract_day + , subq_1.metric_time__extract_dow AS metric_time__extract_dow + , subq_1.metric_time__extract_doy AS metric_time__extract_doy + , subq_1.user AS user + , subq_1.revenue_instance__user AS revenue_instance__user + , subq_1.txn_revenue AS txn_revenue + FROM ( + -- Time Spine + SELECT + subq_3.ds AS metric_time__day + , DATE_TRUNC('week', subq_3.ds) AS metric_time__week + , DATE_TRUNC('quarter', subq_3.ds) AS metric_time__quarter + FROM ***************************.mf_time_spine subq_3 + GROUP BY + subq_3.ds + , DATE_TRUNC('week', subq_3.ds) + , DATE_TRUNC('quarter', subq_3.ds) + ) 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.revenue_instance__ds__day + , subq_0.revenue_instance__ds__week + , subq_0.revenue_instance__ds__month + , subq_0.revenue_instance__ds__quarter + , subq_0.revenue_instance__ds__year + , subq_0.revenue_instance__ds__extract_year + , subq_0.revenue_instance__ds__extract_quarter + , subq_0.revenue_instance__ds__extract_month + , subq_0.revenue_instance__ds__extract_day + , subq_0.revenue_instance__ds__extract_dow + , subq_0.revenue_instance__ds__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.user + , subq_0.revenue_instance__user + , subq_0.txn_revenue + FROM ( + -- Read Elements From Semantic Model 'revenue' + SELECT + revenue_src_28000.revenue AS txn_revenue + , DATE_TRUNC('day', revenue_src_28000.created_at) AS ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS ds__extract_doy + , DATE_TRUNC('day', revenue_src_28000.created_at) AS revenue_instance__ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS revenue_instance__ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS revenue_instance__ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS revenue_instance__ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS revenue_instance__ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_doy + , revenue_src_28000.user_id AS user + , revenue_src_28000.user_id AS revenue_instance__user + FROM ***************************.fct_revenue revenue_src_28000 + ) subq_0 + ) subq_1 + ON + ( + subq_1.metric_time__day <= subq_2.metric_time__day + ) AND ( + subq_1.metric_time__day >= DATE_TRUNC('month', subq_2.metric_time__day) + ) + ) subq_4 + ) subq_5 + GROUP BY + subq_5.metric_time__day + , subq_5.metric_time__week + , subq_5.metric_time__quarter + ) subq_6 + ) subq_7 +) subq_8 +GROUP BY + subq_8.metric_time__week + , subq_8.metric_time__quarter + , subq_8.revenue_mtd diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_all_time_metric_with_multiple_grains__plan0_optimized.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_all_time_metric_with_multiple_grains__plan0_optimized.sql new file mode 100644 index 0000000000..010fda2de8 --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_all_time_metric_with_multiple_grains__plan0_optimized.sql @@ -0,0 +1,56 @@ +-- Re-aggregate Metrics via Window Functions +SELECT + metric_time__week + , metric_time__quarter + , revenue_mtd +FROM ( + SELECT + metric_time__week + , metric_time__quarter + , FIRST_VALUE(revenue_mtd) OVER ( + PARTITION BY + metric_time__week + , metric_time__quarter + ORDER BY metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS revenue_mtd + FROM ( + -- Join Self Over Time Range + -- Pass Only Elements: ['txn_revenue', 'metric_time__week', 'metric_time__quarter', 'metric_time__day'] + -- Aggregate Measures + -- Compute Metrics via Expressions + SELECT + subq_11.metric_time__day AS metric_time__day + , subq_11.metric_time__week AS metric_time__week + , subq_11.metric_time__quarter AS metric_time__quarter + , SUM(revenue_src_28000.revenue) AS revenue_mtd + FROM ( + -- Time Spine + SELECT + ds AS metric_time__day + , DATE_TRUNC('week', ds) AS metric_time__week + , DATE_TRUNC('quarter', ds) AS metric_time__quarter + FROM ***************************.mf_time_spine subq_12 + GROUP BY + ds + , DATE_TRUNC('week', ds) + , DATE_TRUNC('quarter', ds) + ) subq_11 + INNER JOIN + ***************************.fct_revenue revenue_src_28000 + ON + ( + DATE_TRUNC('day', revenue_src_28000.created_at) <= subq_11.metric_time__day + ) AND ( + DATE_TRUNC('day', revenue_src_28000.created_at) >= DATE_TRUNC('month', subq_11.metric_time__day) + ) + GROUP BY + subq_11.metric_time__day + , subq_11.metric_time__week + , subq_11.metric_time__quarter + ) subq_16 +) subq_17 +GROUP BY + metric_time__week + , metric_time__quarter + , revenue_mtd diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_cumulative_metric_with_non_default_grain__plan0.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_cumulative_metric_with_non_default_grain__plan0.sql new file mode 100644 index 0000000000..adee85c66f --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_cumulative_metric_with_non_default_grain__plan0.sql @@ -0,0 +1,162 @@ +-- Re-aggregate Metrics via Window Functions +SELECT + subq_8.metric_time__week + , subq_8.revenue_all_time +FROM ( + SELECT + subq_7.metric_time__week + , FIRST_VALUE(subq_7.revenue_all_time) OVER ( + PARTITION BY subq_7.metric_time__week + ORDER BY subq_7.metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS revenue_all_time + FROM ( + -- Compute Metrics via Expressions + SELECT + subq_6.metric_time__day + , subq_6.metric_time__week + , subq_6.txn_revenue AS revenue_all_time + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__day + , subq_5.metric_time__week + , SUM(subq_5.txn_revenue) AS txn_revenue + FROM ( + -- Pass Only Elements: ['txn_revenue', 'metric_time__week', 'metric_time__day'] + SELECT + subq_4.metric_time__day + , subq_4.metric_time__week + , subq_4.txn_revenue + FROM ( + -- Join Self Over Time Range + SELECT + subq_2.metric_time__day AS metric_time__day + , subq_2.metric_time__week AS metric_time__week + , 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.revenue_instance__ds__day AS revenue_instance__ds__day + , subq_1.revenue_instance__ds__week AS revenue_instance__ds__week + , subq_1.revenue_instance__ds__month AS revenue_instance__ds__month + , subq_1.revenue_instance__ds__quarter AS revenue_instance__ds__quarter + , subq_1.revenue_instance__ds__year AS revenue_instance__ds__year + , subq_1.revenue_instance__ds__extract_year AS revenue_instance__ds__extract_year + , subq_1.revenue_instance__ds__extract_quarter AS revenue_instance__ds__extract_quarter + , subq_1.revenue_instance__ds__extract_month AS revenue_instance__ds__extract_month + , subq_1.revenue_instance__ds__extract_day AS revenue_instance__ds__extract_day + , subq_1.revenue_instance__ds__extract_dow AS revenue_instance__ds__extract_dow + , subq_1.revenue_instance__ds__extract_doy AS revenue_instance__ds__extract_doy + , subq_1.metric_time__month AS metric_time__month + , subq_1.metric_time__quarter AS metric_time__quarter + , subq_1.metric_time__year AS metric_time__year + , subq_1.metric_time__extract_year AS metric_time__extract_year + , subq_1.metric_time__extract_quarter AS metric_time__extract_quarter + , subq_1.metric_time__extract_month AS metric_time__extract_month + , subq_1.metric_time__extract_day AS metric_time__extract_day + , subq_1.metric_time__extract_dow AS metric_time__extract_dow + , subq_1.metric_time__extract_doy AS metric_time__extract_doy + , subq_1.user AS user + , subq_1.revenue_instance__user AS revenue_instance__user + , subq_1.txn_revenue AS txn_revenue + FROM ( + -- Time Spine + SELECT + subq_3.ds AS metric_time__day + , DATE_TRUNC('week', subq_3.ds) AS metric_time__week + FROM ***************************.mf_time_spine subq_3 + GROUP BY + subq_3.ds + , DATE_TRUNC('week', subq_3.ds) + ) 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.revenue_instance__ds__day + , subq_0.revenue_instance__ds__week + , subq_0.revenue_instance__ds__month + , subq_0.revenue_instance__ds__quarter + , subq_0.revenue_instance__ds__year + , subq_0.revenue_instance__ds__extract_year + , subq_0.revenue_instance__ds__extract_quarter + , subq_0.revenue_instance__ds__extract_month + , subq_0.revenue_instance__ds__extract_day + , subq_0.revenue_instance__ds__extract_dow + , subq_0.revenue_instance__ds__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.user + , subq_0.revenue_instance__user + , subq_0.txn_revenue + FROM ( + -- Read Elements From Semantic Model 'revenue' + SELECT + revenue_src_28000.revenue AS txn_revenue + , DATE_TRUNC('day', revenue_src_28000.created_at) AS ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS ds__extract_doy + , DATE_TRUNC('day', revenue_src_28000.created_at) AS revenue_instance__ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS revenue_instance__ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS revenue_instance__ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS revenue_instance__ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS revenue_instance__ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_doy + , revenue_src_28000.user_id AS user + , revenue_src_28000.user_id AS revenue_instance__user + FROM ***************************.fct_revenue revenue_src_28000 + ) subq_0 + ) subq_1 + ON + (subq_1.metric_time__day <= subq_2.metric_time__day) + ) subq_4 + ) subq_5 + GROUP BY + subq_5.metric_time__day + , subq_5.metric_time__week + ) subq_6 + ) subq_7 +) subq_8 +GROUP BY + subq_8.metric_time__week + , subq_8.revenue_all_time diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_cumulative_metric_with_non_default_grain__plan0_optimized.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_cumulative_metric_with_non_default_grain__plan0_optimized.sql new file mode 100644 index 0000000000..0f138fc252 --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_cumulative_metric_with_non_default_grain__plan0_optimized.sql @@ -0,0 +1,45 @@ +-- Re-aggregate Metrics via Window Functions +SELECT + metric_time__week + , revenue_all_time +FROM ( + SELECT + metric_time__week + , FIRST_VALUE(revenue_all_time) OVER ( + PARTITION BY metric_time__week + ORDER BY metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS revenue_all_time + FROM ( + -- Join Self Over Time Range + -- Pass Only Elements: ['txn_revenue', 'metric_time__week', 'metric_time__day'] + -- Aggregate Measures + -- Compute Metrics via Expressions + SELECT + subq_11.metric_time__day AS metric_time__day + , subq_11.metric_time__week AS metric_time__week + , SUM(revenue_src_28000.revenue) AS revenue_all_time + FROM ( + -- Time Spine + SELECT + ds AS metric_time__day + , DATE_TRUNC('week', ds) AS metric_time__week + FROM ***************************.mf_time_spine subq_12 + GROUP BY + ds + , DATE_TRUNC('week', ds) + ) subq_11 + INNER JOIN + ***************************.fct_revenue revenue_src_28000 + ON + ( + DATE_TRUNC('day', revenue_src_28000.created_at) <= subq_11.metric_time__day + ) + GROUP BY + subq_11.metric_time__day + , subq_11.metric_time__week + ) subq_16 +) subq_17 +GROUP BY + metric_time__week + , revenue_all_time diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_derived_cumulative_metric_with_non_default_grain__plan0.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_derived_cumulative_metric_with_non_default_grain__plan0.sql new file mode 100644 index 0000000000..a6005ff109 --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_derived_cumulative_metric_with_non_default_grain__plan0.sql @@ -0,0 +1,172 @@ +-- Compute Metrics via Expressions +SELECT + subq_9.metric_time__week + , t2mr - 10 AS trailing_2_months_revenue_sub_10 +FROM ( + -- Re-aggregate Metrics via Window Functions + SELECT + subq_8.metric_time__week + , subq_8.t2mr + FROM ( + SELECT + subq_7.metric_time__week + , FIRST_VALUE(subq_7.t2mr) OVER ( + PARTITION BY subq_7.metric_time__week + ORDER BY subq_7.metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS t2mr + FROM ( + -- Compute Metrics via Expressions + SELECT + subq_6.metric_time__day + , subq_6.metric_time__week + , subq_6.txn_revenue AS t2mr + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__day + , subq_5.metric_time__week + , SUM(subq_5.txn_revenue) AS txn_revenue + FROM ( + -- Pass Only Elements: ['txn_revenue', 'metric_time__week', 'metric_time__day'] + SELECT + subq_4.metric_time__day + , subq_4.metric_time__week + , subq_4.txn_revenue + FROM ( + -- Join Self Over Time Range + SELECT + subq_2.metric_time__day AS metric_time__day + , subq_2.metric_time__week AS metric_time__week + , 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.revenue_instance__ds__day AS revenue_instance__ds__day + , subq_1.revenue_instance__ds__week AS revenue_instance__ds__week + , subq_1.revenue_instance__ds__month AS revenue_instance__ds__month + , subq_1.revenue_instance__ds__quarter AS revenue_instance__ds__quarter + , subq_1.revenue_instance__ds__year AS revenue_instance__ds__year + , subq_1.revenue_instance__ds__extract_year AS revenue_instance__ds__extract_year + , subq_1.revenue_instance__ds__extract_quarter AS revenue_instance__ds__extract_quarter + , subq_1.revenue_instance__ds__extract_month AS revenue_instance__ds__extract_month + , subq_1.revenue_instance__ds__extract_day AS revenue_instance__ds__extract_day + , subq_1.revenue_instance__ds__extract_dow AS revenue_instance__ds__extract_dow + , subq_1.revenue_instance__ds__extract_doy AS revenue_instance__ds__extract_doy + , subq_1.metric_time__month AS metric_time__month + , subq_1.metric_time__quarter AS metric_time__quarter + , subq_1.metric_time__year AS metric_time__year + , subq_1.metric_time__extract_year AS metric_time__extract_year + , subq_1.metric_time__extract_quarter AS metric_time__extract_quarter + , subq_1.metric_time__extract_month AS metric_time__extract_month + , subq_1.metric_time__extract_day AS metric_time__extract_day + , subq_1.metric_time__extract_dow AS metric_time__extract_dow + , subq_1.metric_time__extract_doy AS metric_time__extract_doy + , subq_1.user AS user + , subq_1.revenue_instance__user AS revenue_instance__user + , subq_1.txn_revenue AS txn_revenue + FROM ( + -- Time Spine + SELECT + subq_3.ds AS metric_time__day + , DATE_TRUNC('week', subq_3.ds) AS metric_time__week + FROM ***************************.mf_time_spine subq_3 + GROUP BY + subq_3.ds + , DATE_TRUNC('week', subq_3.ds) + ) 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.revenue_instance__ds__day + , subq_0.revenue_instance__ds__week + , subq_0.revenue_instance__ds__month + , subq_0.revenue_instance__ds__quarter + , subq_0.revenue_instance__ds__year + , subq_0.revenue_instance__ds__extract_year + , subq_0.revenue_instance__ds__extract_quarter + , subq_0.revenue_instance__ds__extract_month + , subq_0.revenue_instance__ds__extract_day + , subq_0.revenue_instance__ds__extract_dow + , subq_0.revenue_instance__ds__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.user + , subq_0.revenue_instance__user + , subq_0.txn_revenue + FROM ( + -- Read Elements From Semantic Model 'revenue' + SELECT + revenue_src_28000.revenue AS txn_revenue + , DATE_TRUNC('day', revenue_src_28000.created_at) AS ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS ds__extract_doy + , DATE_TRUNC('day', revenue_src_28000.created_at) AS revenue_instance__ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS revenue_instance__ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS revenue_instance__ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS revenue_instance__ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS revenue_instance__ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_doy + , revenue_src_28000.user_id AS user + , revenue_src_28000.user_id AS revenue_instance__user + FROM ***************************.fct_revenue revenue_src_28000 + ) subq_0 + ) subq_1 + ON + ( + subq_1.metric_time__day <= subq_2.metric_time__day + ) AND ( + subq_1.metric_time__day > subq_2.metric_time__day - INTERVAL 2 month + ) + ) subq_4 + ) subq_5 + GROUP BY + subq_5.metric_time__day + , subq_5.metric_time__week + ) subq_6 + ) subq_7 + ) subq_8 + GROUP BY + subq_8.metric_time__week + , subq_8.t2mr +) subq_9 diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_derived_cumulative_metric_with_non_default_grain__plan0_optimized.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_derived_cumulative_metric_with_non_default_grain__plan0_optimized.sql new file mode 100644 index 0000000000..f8eb61fe20 --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_derived_cumulative_metric_with_non_default_grain__plan0_optimized.sql @@ -0,0 +1,53 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__week + , t2mr - 10 AS trailing_2_months_revenue_sub_10 +FROM ( + -- Re-aggregate Metrics via Window Functions + SELECT + metric_time__week + , t2mr + FROM ( + SELECT + metric_time__week + , FIRST_VALUE(t2mr) OVER ( + PARTITION BY metric_time__week + ORDER BY metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS t2mr + FROM ( + -- Join Self Over Time Range + -- Pass Only Elements: ['txn_revenue', 'metric_time__week', 'metric_time__day'] + -- Aggregate Measures + -- Compute Metrics via Expressions + SELECT + subq_12.metric_time__day AS metric_time__day + , subq_12.metric_time__week AS metric_time__week + , SUM(revenue_src_28000.revenue) AS t2mr + FROM ( + -- Time Spine + SELECT + ds AS metric_time__day + , DATE_TRUNC('week', ds) AS metric_time__week + FROM ***************************.mf_time_spine subq_13 + GROUP BY + ds + , DATE_TRUNC('week', ds) + ) subq_12 + INNER JOIN + ***************************.fct_revenue revenue_src_28000 + ON + ( + DATE_TRUNC('day', revenue_src_28000.created_at) <= subq_12.metric_time__day + ) AND ( + DATE_TRUNC('day', revenue_src_28000.created_at) > subq_12.metric_time__day - INTERVAL 2 month + ) + GROUP BY + subq_12.metric_time__day + , subq_12.metric_time__week + ) subq_17 + ) subq_18 + GROUP BY + metric_time__week + , t2mr +) subq_19 diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_multiple_grains__plan0.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_multiple_grains__plan0.sql new file mode 100644 index 0000000000..824539bb13 --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_multiple_grains__plan0.sql @@ -0,0 +1,177 @@ +-- Re-aggregate Metrics via Window Functions +SELECT + subq_8.revenue_instance__ds__quarter + , subq_8.revenue_instance__ds__year + , subq_8.revenue_mtd +FROM ( + SELECT + subq_7.revenue_instance__ds__quarter + , subq_7.revenue_instance__ds__year + , FIRST_VALUE(subq_7.revenue_mtd) OVER ( + PARTITION BY + subq_7.revenue_instance__ds__quarter + , subq_7.revenue_instance__ds__year + ORDER BY subq_7.metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS revenue_mtd + FROM ( + -- Compute Metrics via Expressions + SELECT + subq_6.revenue_instance__ds__quarter + , subq_6.revenue_instance__ds__year + , subq_6.metric_time__day + , subq_6.txn_revenue AS revenue_mtd + FROM ( + -- Aggregate Measures + SELECT + subq_5.revenue_instance__ds__quarter + , subq_5.revenue_instance__ds__year + , subq_5.metric_time__day + , SUM(subq_5.txn_revenue) AS txn_revenue + FROM ( + -- Pass Only Elements: ['txn_revenue', 'revenue_instance__ds__quarter', 'revenue_instance__ds__year', 'metric_time__day'] + SELECT + subq_4.revenue_instance__ds__quarter + , subq_4.revenue_instance__ds__year + , subq_4.metric_time__day + , subq_4.txn_revenue + FROM ( + -- Join Self Over Time Range + SELECT + subq_2.revenue_instance__ds__quarter AS revenue_instance__ds__quarter + , subq_2.revenue_instance__ds__year AS revenue_instance__ds__year + , subq_2.metric_time__day AS metric_time__day + , 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.revenue_instance__ds__day AS revenue_instance__ds__day + , subq_1.revenue_instance__ds__week AS revenue_instance__ds__week + , subq_1.revenue_instance__ds__month AS revenue_instance__ds__month + , subq_1.revenue_instance__ds__extract_year AS revenue_instance__ds__extract_year + , subq_1.revenue_instance__ds__extract_quarter AS revenue_instance__ds__extract_quarter + , subq_1.revenue_instance__ds__extract_month AS revenue_instance__ds__extract_month + , subq_1.revenue_instance__ds__extract_day AS revenue_instance__ds__extract_day + , subq_1.revenue_instance__ds__extract_dow AS revenue_instance__ds__extract_dow + , subq_1.revenue_instance__ds__extract_doy AS revenue_instance__ds__extract_doy + , subq_1.metric_time__week AS metric_time__week + , subq_1.metric_time__month AS metric_time__month + , subq_1.metric_time__quarter AS metric_time__quarter + , subq_1.metric_time__year AS metric_time__year + , subq_1.metric_time__extract_year AS metric_time__extract_year + , subq_1.metric_time__extract_quarter AS metric_time__extract_quarter + , subq_1.metric_time__extract_month AS metric_time__extract_month + , subq_1.metric_time__extract_day AS metric_time__extract_day + , subq_1.metric_time__extract_dow AS metric_time__extract_dow + , subq_1.metric_time__extract_doy AS metric_time__extract_doy + , subq_1.user AS user + , subq_1.revenue_instance__user AS revenue_instance__user + , subq_1.txn_revenue AS txn_revenue + FROM ( + -- Time Spine + SELECT + DATE_TRUNC('quarter', subq_3.ds) AS revenue_instance__ds__quarter + , DATE_TRUNC('year', subq_3.ds) AS revenue_instance__ds__year + , subq_3.ds AS metric_time__day + FROM ***************************.mf_time_spine subq_3 + GROUP BY + DATE_TRUNC('quarter', subq_3.ds) + , DATE_TRUNC('year', subq_3.ds) + , subq_3.ds + ) 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.revenue_instance__ds__day + , subq_0.revenue_instance__ds__week + , subq_0.revenue_instance__ds__month + , subq_0.revenue_instance__ds__quarter + , subq_0.revenue_instance__ds__year + , subq_0.revenue_instance__ds__extract_year + , subq_0.revenue_instance__ds__extract_quarter + , subq_0.revenue_instance__ds__extract_month + , subq_0.revenue_instance__ds__extract_day + , subq_0.revenue_instance__ds__extract_dow + , subq_0.revenue_instance__ds__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.user + , subq_0.revenue_instance__user + , subq_0.txn_revenue + FROM ( + -- Read Elements From Semantic Model 'revenue' + SELECT + revenue_src_28000.revenue AS txn_revenue + , DATE_TRUNC('day', revenue_src_28000.created_at) AS ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS ds__extract_doy + , DATE_TRUNC('day', revenue_src_28000.created_at) AS revenue_instance__ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS revenue_instance__ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS revenue_instance__ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS revenue_instance__ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS revenue_instance__ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_doy + , revenue_src_28000.user_id AS user + , revenue_src_28000.user_id AS revenue_instance__user + FROM ***************************.fct_revenue revenue_src_28000 + ) subq_0 + ) subq_1 + ON + ( + subq_1.metric_time__day <= subq_2.metric_time__day + ) AND ( + subq_1.metric_time__day >= DATE_TRUNC('month', subq_2.metric_time__day) + ) + ) subq_4 + ) subq_5 + GROUP BY + subq_5.revenue_instance__ds__quarter + , subq_5.revenue_instance__ds__year + , subq_5.metric_time__day + ) subq_6 + ) subq_7 +) subq_8 +GROUP BY + subq_8.revenue_instance__ds__quarter + , subq_8.revenue_instance__ds__year + , subq_8.revenue_mtd diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_multiple_grains__plan0_optimized.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_multiple_grains__plan0_optimized.sql new file mode 100644 index 0000000000..a86c1c9576 --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_multiple_grains__plan0_optimized.sql @@ -0,0 +1,56 @@ +-- Re-aggregate Metrics via Window Functions +SELECT + revenue_instance__ds__quarter + , revenue_instance__ds__year + , revenue_mtd +FROM ( + SELECT + revenue_instance__ds__quarter + , revenue_instance__ds__year + , FIRST_VALUE(revenue_mtd) OVER ( + PARTITION BY + revenue_instance__ds__quarter + , revenue_instance__ds__year + ORDER BY metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS revenue_mtd + FROM ( + -- Join Self Over Time Range + -- Pass Only Elements: ['txn_revenue', 'revenue_instance__ds__quarter', 'revenue_instance__ds__year', 'metric_time__day'] + -- Aggregate Measures + -- Compute Metrics via Expressions + SELECT + subq_11.revenue_instance__ds__quarter AS revenue_instance__ds__quarter + , subq_11.revenue_instance__ds__year AS revenue_instance__ds__year + , subq_11.metric_time__day AS metric_time__day + , SUM(revenue_src_28000.revenue) AS revenue_mtd + FROM ( + -- Time Spine + SELECT + DATE_TRUNC('quarter', ds) AS revenue_instance__ds__quarter + , DATE_TRUNC('year', ds) AS revenue_instance__ds__year + , ds AS metric_time__day + FROM ***************************.mf_time_spine subq_12 + GROUP BY + DATE_TRUNC('quarter', ds) + , DATE_TRUNC('year', ds) + , ds + ) subq_11 + INNER JOIN + ***************************.fct_revenue revenue_src_28000 + ON + ( + DATE_TRUNC('day', revenue_src_28000.created_at) <= subq_11.metric_time__day + ) AND ( + DATE_TRUNC('day', revenue_src_28000.created_at) >= DATE_TRUNC('month', subq_11.metric_time__day) + ) + GROUP BY + subq_11.revenue_instance__ds__quarter + , subq_11.revenue_instance__ds__year + , subq_11.metric_time__day + ) subq_16 +) subq_17 +GROUP BY + revenue_instance__ds__quarter + , revenue_instance__ds__year + , revenue_mtd diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_non_default_grain__plan0.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_non_default_grain__plan0.sql new file mode 100644 index 0000000000..1f970f5692 --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_non_default_grain__plan0.sql @@ -0,0 +1,166 @@ +-- Re-aggregate Metrics via Window Functions +SELECT + subq_8.metric_time__month + , subq_8.revenue_mtd +FROM ( + SELECT + subq_7.metric_time__month + , FIRST_VALUE(subq_7.revenue_mtd) OVER ( + PARTITION BY subq_7.metric_time__month + ORDER BY subq_7.metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS revenue_mtd + FROM ( + -- Compute Metrics via Expressions + SELECT + subq_6.metric_time__day + , subq_6.metric_time__month + , subq_6.txn_revenue AS revenue_mtd + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__day + , subq_5.metric_time__month + , SUM(subq_5.txn_revenue) AS txn_revenue + FROM ( + -- Pass Only Elements: ['txn_revenue', 'metric_time__month', 'metric_time__day'] + SELECT + subq_4.metric_time__day + , subq_4.metric_time__month + , subq_4.txn_revenue + FROM ( + -- Join Self Over Time Range + SELECT + subq_2.metric_time__day AS metric_time__day + , subq_2.metric_time__month AS metric_time__month + , 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.revenue_instance__ds__day AS revenue_instance__ds__day + , subq_1.revenue_instance__ds__week AS revenue_instance__ds__week + , subq_1.revenue_instance__ds__month AS revenue_instance__ds__month + , subq_1.revenue_instance__ds__quarter AS revenue_instance__ds__quarter + , subq_1.revenue_instance__ds__year AS revenue_instance__ds__year + , subq_1.revenue_instance__ds__extract_year AS revenue_instance__ds__extract_year + , subq_1.revenue_instance__ds__extract_quarter AS revenue_instance__ds__extract_quarter + , subq_1.revenue_instance__ds__extract_month AS revenue_instance__ds__extract_month + , subq_1.revenue_instance__ds__extract_day AS revenue_instance__ds__extract_day + , subq_1.revenue_instance__ds__extract_dow AS revenue_instance__ds__extract_dow + , subq_1.revenue_instance__ds__extract_doy AS revenue_instance__ds__extract_doy + , subq_1.metric_time__week AS metric_time__week + , subq_1.metric_time__quarter AS metric_time__quarter + , subq_1.metric_time__year AS metric_time__year + , subq_1.metric_time__extract_year AS metric_time__extract_year + , subq_1.metric_time__extract_quarter AS metric_time__extract_quarter + , subq_1.metric_time__extract_month AS metric_time__extract_month + , subq_1.metric_time__extract_day AS metric_time__extract_day + , subq_1.metric_time__extract_dow AS metric_time__extract_dow + , subq_1.metric_time__extract_doy AS metric_time__extract_doy + , subq_1.user AS user + , subq_1.revenue_instance__user AS revenue_instance__user + , subq_1.txn_revenue AS txn_revenue + FROM ( + -- Time Spine + SELECT + subq_3.ds AS metric_time__day + , DATE_TRUNC('month', subq_3.ds) AS metric_time__month + FROM ***************************.mf_time_spine subq_3 + GROUP BY + subq_3.ds + , DATE_TRUNC('month', subq_3.ds) + ) 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.revenue_instance__ds__day + , subq_0.revenue_instance__ds__week + , subq_0.revenue_instance__ds__month + , subq_0.revenue_instance__ds__quarter + , subq_0.revenue_instance__ds__year + , subq_0.revenue_instance__ds__extract_year + , subq_0.revenue_instance__ds__extract_quarter + , subq_0.revenue_instance__ds__extract_month + , subq_0.revenue_instance__ds__extract_day + , subq_0.revenue_instance__ds__extract_dow + , subq_0.revenue_instance__ds__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.user + , subq_0.revenue_instance__user + , subq_0.txn_revenue + FROM ( + -- Read Elements From Semantic Model 'revenue' + SELECT + revenue_src_28000.revenue AS txn_revenue + , DATE_TRUNC('day', revenue_src_28000.created_at) AS ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS ds__extract_doy + , DATE_TRUNC('day', revenue_src_28000.created_at) AS revenue_instance__ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS revenue_instance__ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS revenue_instance__ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS revenue_instance__ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS revenue_instance__ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_doy + , revenue_src_28000.user_id AS user + , revenue_src_28000.user_id AS revenue_instance__user + FROM ***************************.fct_revenue revenue_src_28000 + ) subq_0 + ) subq_1 + ON + ( + subq_1.metric_time__day <= subq_2.metric_time__day + ) AND ( + subq_1.metric_time__day >= DATE_TRUNC('month', subq_2.metric_time__day) + ) + ) subq_4 + ) subq_5 + GROUP BY + subq_5.metric_time__day + , subq_5.metric_time__month + ) subq_6 + ) subq_7 +) subq_8 +GROUP BY + subq_8.metric_time__month + , subq_8.revenue_mtd diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_non_default_grain__plan0_optimized.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_non_default_grain__plan0_optimized.sql new file mode 100644 index 0000000000..e99370b8b2 --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_grain_to_date_metric_with_non_default_grain__plan0_optimized.sql @@ -0,0 +1,47 @@ +-- Re-aggregate Metrics via Window Functions +SELECT + metric_time__month + , revenue_mtd +FROM ( + SELECT + metric_time__month + , FIRST_VALUE(revenue_mtd) OVER ( + PARTITION BY metric_time__month + ORDER BY metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS revenue_mtd + FROM ( + -- Join Self Over Time Range + -- Pass Only Elements: ['txn_revenue', 'metric_time__month', 'metric_time__day'] + -- Aggregate Measures + -- Compute Metrics via Expressions + SELECT + subq_11.metric_time__day AS metric_time__day + , subq_11.metric_time__month AS metric_time__month + , SUM(revenue_src_28000.revenue) AS revenue_mtd + FROM ( + -- Time Spine + SELECT + ds AS metric_time__day + , DATE_TRUNC('month', ds) AS metric_time__month + FROM ***************************.mf_time_spine subq_12 + GROUP BY + ds + , DATE_TRUNC('month', ds) + ) subq_11 + INNER JOIN + ***************************.fct_revenue revenue_src_28000 + ON + ( + DATE_TRUNC('day', revenue_src_28000.created_at) <= subq_11.metric_time__day + ) AND ( + DATE_TRUNC('day', revenue_src_28000.created_at) >= DATE_TRUNC('month', subq_11.metric_time__day) + ) + GROUP BY + subq_11.metric_time__day + , subq_11.metric_time__month + ) subq_16 +) subq_17 +GROUP BY + metric_time__month + , revenue_mtd diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_multiple_grains__plan0.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_multiple_grains__plan0.sql new file mode 100644 index 0000000000..1b3fcc37a1 --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_multiple_grains__plan0.sql @@ -0,0 +1,350 @@ +-- Compute Metrics via Expressions +SELECT + subq_9.metric_time__day + , subq_9.booking__ds__month + , COALESCE(subq_9.bookers, 0) AS every_two_days_bookers_fill_nulls_with_0 +FROM ( + -- Join to Time Spine Dataset + SELECT + subq_7.metric_time__day AS metric_time__day + , subq_6.booking__ds__month AS booking__ds__month + , subq_6.bookers AS bookers + FROM ( + -- Time Spine + SELECT + subq_8.ds AS metric_time__day + FROM ***************************.mf_time_spine subq_8 + ) subq_7 + LEFT OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_5.booking__ds__month + , subq_5.metric_time__day + , COUNT(DISTINCT subq_5.bookers) AS bookers + FROM ( + -- Pass Only Elements: ['bookers', 'metric_time__day', 'booking__ds__month'] + SELECT + subq_4.booking__ds__month + , subq_4.metric_time__day + , subq_4.bookers + FROM ( + -- Join Self Over Time Range + SELECT + subq_2.booking__ds__month AS booking__ds__month + , subq_2.metric_time__day AS metric_time__day + , 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__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.metric_time__week AS metric_time__week + , subq_1.metric_time__month AS metric_time__month + , subq_1.metric_time__quarter AS metric_time__quarter + , subq_1.metric_time__year AS metric_time__year + , subq_1.metric_time__extract_year AS metric_time__extract_year + , subq_1.metric_time__extract_quarter AS metric_time__extract_quarter + , subq_1.metric_time__extract_month AS metric_time__extract_month + , subq_1.metric_time__extract_day AS metric_time__extract_day + , subq_1.metric_time__extract_dow AS metric_time__extract_dow + , subq_1.metric_time__extract_doy AS metric_time__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 ( + -- Time Spine + SELECT + DATE_TRUNC('month', subq_3.ds) AS booking__ds__month + , subq_3.ds AS metric_time__day + FROM ***************************.mf_time_spine subq_3 + GROUP BY + DATE_TRUNC('month', subq_3.ds) + , subq_3.ds + ) 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_1.metric_time__day <= subq_2.metric_time__day + ) AND ( + subq_1.metric_time__day > subq_2.metric_time__day - INTERVAL 2 day + ) + ) subq_4 + ) subq_5 + GROUP BY + subq_5.booking__ds__month + , subq_5.metric_time__day + ) subq_6 + ON + subq_7.metric_time__day = subq_6.metric_time__day +) subq_9 diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_multiple_grains__plan0_optimized.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_multiple_grains__plan0_optimized.sql new file mode 100644 index 0000000000..164666657d --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_multiple_grains__plan0_optimized.sql @@ -0,0 +1,45 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__day + , booking__ds__month + , COALESCE(bookers, 0) AS every_two_days_bookers_fill_nulls_with_0 +FROM ( + -- Join to Time Spine Dataset + SELECT + subq_18.ds AS metric_time__day + , subq_16.booking__ds__month AS booking__ds__month + , subq_16.bookers AS bookers + FROM ***************************.mf_time_spine subq_18 + LEFT OUTER JOIN ( + -- Join Self Over Time Range + -- Pass Only Elements: ['bookers', 'metric_time__day', 'booking__ds__month'] + -- Aggregate Measures + SELECT + subq_12.booking__ds__month AS booking__ds__month + , subq_12.metric_time__day AS metric_time__day + , COUNT(DISTINCT bookings_source_src_28000.guest_id) AS bookers + FROM ( + -- Time Spine + SELECT + DATE_TRUNC('month', ds) AS booking__ds__month + , ds AS metric_time__day + FROM ***************************.mf_time_spine subq_13 + GROUP BY + DATE_TRUNC('month', ds) + , ds + ) subq_12 + INNER JOIN + ***************************.fct_bookings bookings_source_src_28000 + ON + ( + DATE_TRUNC('day', bookings_source_src_28000.ds) <= subq_12.metric_time__day + ) AND ( + DATE_TRUNC('day', bookings_source_src_28000.ds) > subq_12.metric_time__day - INTERVAL 2 day + ) + GROUP BY + subq_12.booking__ds__month + , subq_12.metric_time__day + ) subq_16 + ON + subq_18.ds = subq_16.metric_time__day +) subq_19 diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_non_default_grain__plan0.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_non_default_grain__plan0.sql new file mode 100644 index 0000000000..5b9bc20a85 --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_non_default_grain__plan0.sql @@ -0,0 +1,166 @@ +-- Re-aggregate Metrics via Window Functions +SELECT + subq_8.metric_time__year + , subq_8.trailing_2_months_revenue +FROM ( + SELECT + subq_7.metric_time__year + , FIRST_VALUE(subq_7.trailing_2_months_revenue) OVER ( + PARTITION BY subq_7.metric_time__year + ORDER BY subq_7.metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS trailing_2_months_revenue + FROM ( + -- Compute Metrics via Expressions + SELECT + subq_6.metric_time__day + , subq_6.metric_time__year + , subq_6.txn_revenue AS trailing_2_months_revenue + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__day + , subq_5.metric_time__year + , SUM(subq_5.txn_revenue) AS txn_revenue + FROM ( + -- Pass Only Elements: ['txn_revenue', 'metric_time__year', 'metric_time__day'] + SELECT + subq_4.metric_time__day + , subq_4.metric_time__year + , subq_4.txn_revenue + FROM ( + -- Join Self Over Time Range + SELECT + subq_2.metric_time__day AS metric_time__day + , subq_2.metric_time__year AS metric_time__year + , 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.revenue_instance__ds__day AS revenue_instance__ds__day + , subq_1.revenue_instance__ds__week AS revenue_instance__ds__week + , subq_1.revenue_instance__ds__month AS revenue_instance__ds__month + , subq_1.revenue_instance__ds__quarter AS revenue_instance__ds__quarter + , subq_1.revenue_instance__ds__year AS revenue_instance__ds__year + , subq_1.revenue_instance__ds__extract_year AS revenue_instance__ds__extract_year + , subq_1.revenue_instance__ds__extract_quarter AS revenue_instance__ds__extract_quarter + , subq_1.revenue_instance__ds__extract_month AS revenue_instance__ds__extract_month + , subq_1.revenue_instance__ds__extract_day AS revenue_instance__ds__extract_day + , subq_1.revenue_instance__ds__extract_dow AS revenue_instance__ds__extract_dow + , subq_1.revenue_instance__ds__extract_doy AS revenue_instance__ds__extract_doy + , subq_1.metric_time__week AS metric_time__week + , subq_1.metric_time__month AS metric_time__month + , subq_1.metric_time__quarter AS metric_time__quarter + , subq_1.metric_time__extract_year AS metric_time__extract_year + , subq_1.metric_time__extract_quarter AS metric_time__extract_quarter + , subq_1.metric_time__extract_month AS metric_time__extract_month + , subq_1.metric_time__extract_day AS metric_time__extract_day + , subq_1.metric_time__extract_dow AS metric_time__extract_dow + , subq_1.metric_time__extract_doy AS metric_time__extract_doy + , subq_1.user AS user + , subq_1.revenue_instance__user AS revenue_instance__user + , subq_1.txn_revenue AS txn_revenue + FROM ( + -- Time Spine + SELECT + subq_3.ds AS metric_time__day + , DATE_TRUNC('year', subq_3.ds) AS metric_time__year + FROM ***************************.mf_time_spine subq_3 + GROUP BY + subq_3.ds + , DATE_TRUNC('year', subq_3.ds) + ) 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.revenue_instance__ds__day + , subq_0.revenue_instance__ds__week + , subq_0.revenue_instance__ds__month + , subq_0.revenue_instance__ds__quarter + , subq_0.revenue_instance__ds__year + , subq_0.revenue_instance__ds__extract_year + , subq_0.revenue_instance__ds__extract_quarter + , subq_0.revenue_instance__ds__extract_month + , subq_0.revenue_instance__ds__extract_day + , subq_0.revenue_instance__ds__extract_dow + , subq_0.revenue_instance__ds__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.user + , subq_0.revenue_instance__user + , subq_0.txn_revenue + FROM ( + -- Read Elements From Semantic Model 'revenue' + SELECT + revenue_src_28000.revenue AS txn_revenue + , DATE_TRUNC('day', revenue_src_28000.created_at) AS ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS ds__extract_doy + , DATE_TRUNC('day', revenue_src_28000.created_at) AS revenue_instance__ds__day + , DATE_TRUNC('week', revenue_src_28000.created_at) AS revenue_instance__ds__week + , DATE_TRUNC('month', revenue_src_28000.created_at) AS revenue_instance__ds__month + , DATE_TRUNC('quarter', revenue_src_28000.created_at) AS revenue_instance__ds__quarter + , DATE_TRUNC('year', revenue_src_28000.created_at) AS revenue_instance__ds__year + , EXTRACT(year FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_year + , EXTRACT(quarter FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_quarter + , EXTRACT(month FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_month + , EXTRACT(day FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_day + , EXTRACT(isodow FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_dow + , EXTRACT(doy FROM revenue_src_28000.created_at) AS revenue_instance__ds__extract_doy + , revenue_src_28000.user_id AS user + , revenue_src_28000.user_id AS revenue_instance__user + FROM ***************************.fct_revenue revenue_src_28000 + ) subq_0 + ) subq_1 + ON + ( + subq_1.metric_time__day <= subq_2.metric_time__day + ) AND ( + subq_1.metric_time__day > subq_2.metric_time__day - INTERVAL 2 month + ) + ) subq_4 + ) subq_5 + GROUP BY + subq_5.metric_time__day + , subq_5.metric_time__year + ) subq_6 + ) subq_7 +) subq_8 +GROUP BY + subq_8.metric_time__year + , subq_8.trailing_2_months_revenue diff --git a/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_non_default_grain__plan0_optimized.sql b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_non_default_grain__plan0_optimized.sql new file mode 100644 index 0000000000..8e1ddcdede --- /dev/null +++ b/tests_metricflow/snapshots/test_cumulative_metric_rendering.py/SqlQueryPlan/DuckDB/test_window_metric_with_non_default_grain__plan0_optimized.sql @@ -0,0 +1,47 @@ +-- Re-aggregate Metrics via Window Functions +SELECT + metric_time__year + , trailing_2_months_revenue +FROM ( + SELECT + metric_time__year + , FIRST_VALUE(trailing_2_months_revenue) OVER ( + PARTITION BY metric_time__year + ORDER BY metric_time__day + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS trailing_2_months_revenue + FROM ( + -- Join Self Over Time Range + -- Pass Only Elements: ['txn_revenue', 'metric_time__year', 'metric_time__day'] + -- Aggregate Measures + -- Compute Metrics via Expressions + SELECT + subq_11.metric_time__day AS metric_time__day + , subq_11.metric_time__year AS metric_time__year + , SUM(revenue_src_28000.revenue) AS trailing_2_months_revenue + FROM ( + -- Time Spine + SELECT + ds AS metric_time__day + , DATE_TRUNC('year', ds) AS metric_time__year + FROM ***************************.mf_time_spine subq_12 + GROUP BY + ds + , DATE_TRUNC('year', ds) + ) subq_11 + INNER JOIN + ***************************.fct_revenue revenue_src_28000 + ON + ( + DATE_TRUNC('day', revenue_src_28000.created_at) <= subq_11.metric_time__day + ) AND ( + DATE_TRUNC('day', revenue_src_28000.created_at) > subq_11.metric_time__day - INTERVAL 2 month + ) + GROUP BY + subq_11.metric_time__day + , subq_11.metric_time__year + ) subq_16 +) subq_17 +GROUP BY + metric_time__year + , trailing_2_months_revenue