diff --git a/metricflow/test/dataflow/builder/test_dataflow_plan_builder.py b/metricflow/test/dataflow/builder/test_dataflow_plan_builder.py index 1665a9976f..855e8ddbc0 100644 --- a/metricflow/test/dataflow/builder/test_dataflow_plan_builder.py +++ b/metricflow/test/dataflow/builder/test_dataflow_plan_builder.py @@ -1007,7 +1007,7 @@ def test_min_max_only_time( mf_test_session_state: MetricFlowTestSessionState, dataflow_plan_builder: DataflowPlanBuilder, ) -> None: - """Tests a plan to get the min & max distinct values of a categorical dimension.""" + """Tests a plan to get the min & max distinct values of a time dimension.""" dataflow_plan = dataflow_plan_builder.build_plan_for_distinct_values( query_spec=MetricFlowQuerySpec( time_dimension_specs=( @@ -1036,7 +1036,7 @@ def test_min_max_only_time_year( mf_test_session_state: MetricFlowTestSessionState, dataflow_plan_builder: DataflowPlanBuilder, ) -> None: - """Tests a plan to get the min & max distinct values of a categorical dimension.""" + """Tests a plan to get the min & max distinct values of a time dimension with year granularity.""" dataflow_plan = dataflow_plan_builder.build_plan_for_distinct_values( query_spec=MetricFlowQuerySpec( time_dimension_specs=( diff --git a/metricflow/test/integration/test_configured_cases.py b/metricflow/test/integration/test_configured_cases.py index de7faaeb4a..33c8da24b5 100644 --- a/metricflow/test/integration/test_configured_cases.py +++ b/metricflow/test/integration/test_configured_cases.py @@ -298,6 +298,7 @@ def test_case( if case.where_filter else None, order_by_names=case.order_bys, + min_max_only=case.min_max_only, ) ) diff --git a/metricflow/test/query_rendering/test_query_rendering.py b/metricflow/test/query_rendering/test_query_rendering.py index e9684993b0..ec4d487086 100644 --- a/metricflow/test/query_rendering/test_query_rendering.py +++ b/metricflow/test/query_rendering/test_query_rendering.py @@ -500,3 +500,95 @@ def test_common_semantic_model( # noqa: D sql_client=sql_client, node=dataflow_plan.sink_output_nodes[0].parent_node, ) + + +@pytest.mark.sql_engine_snapshot +def test_min_max_only_categorical( + request: FixtureRequest, + mf_test_session_state: MetricFlowTestSessionState, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + sql_client: SqlClient, +) -> None: + """Tests a min max only query with a categorical dimension.""" + dataflow_plan = dataflow_plan_builder.build_plan_for_distinct_values( + query_spec=MetricFlowQuerySpec( + dimension_specs=( + DimensionSpec( + element_name="country_latest", + entity_links=(EntityReference(element_name="listing"),), + ), + ), + min_max_only=True, + ), + ) + + convert_and_check( + request=request, + mf_test_session_state=mf_test_session_state, + dataflow_to_sql_converter=dataflow_to_sql_converter, + sql_client=sql_client, + node=dataflow_plan.sink_output_nodes[0].parent_node, + ) + + +@pytest.mark.sql_engine_snapshot +def test_min_max_only_time( + request: FixtureRequest, + mf_test_session_state: MetricFlowTestSessionState, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + sql_client: SqlClient, +) -> None: + """Tests a min max only query with a time dimension.""" + dataflow_plan = dataflow_plan_builder.build_plan_for_distinct_values( + query_spec=MetricFlowQuerySpec( + time_dimension_specs=( + TimeDimensionSpec( + element_name="paid_at", + entity_links=(EntityReference("booking"),), + time_granularity=TimeGranularity.DAY, + ), + ), + min_max_only=True, + ), + ) + + convert_and_check( + request=request, + mf_test_session_state=mf_test_session_state, + dataflow_to_sql_converter=dataflow_to_sql_converter, + sql_client=sql_client, + node=dataflow_plan.sink_output_nodes[0].parent_node, + ) + + +@pytest.mark.sql_engine_snapshot +def test_min_max_only_time_quarter( + request: FixtureRequest, + mf_test_session_state: MetricFlowTestSessionState, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + sql_client: SqlClient, +) -> None: + """Tests a min max only query with a time dimension and non-default granularity.""" + dataflow_plan = dataflow_plan_builder.build_plan_for_distinct_values( + query_spec=MetricFlowQuerySpec( + time_dimension_specs=( + TimeDimensionSpec( + element_name="paid_at", + entity_links=(EntityReference("booking"),), + time_granularity=TimeGranularity.QUARTER, + ), + ), + min_max_only=True, + ), + ) + + convert_and_check( + request=request, + mf_test_session_state=mf_test_session_state, + dataflow_to_sql_converter=dataflow_to_sql_converter, + sql_client=sql_client, + node=dataflow_plan.sink_output_nodes[0].parent_node, + ) diff --git a/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_categorical__plan0.sql b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_categorical__plan0.sql new file mode 100644 index 0000000000..fa3cc874b3 --- /dev/null +++ b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_categorical__plan0.sql @@ -0,0 +1,73 @@ +-- Calculate min and max +SELECT + MIN(listing__country_latest) AS min + , MAX(listing__country_latest) AS max +FROM ( + -- Pass Only Elements: + -- ['listing__country_latest'] + SELECT + subq_0.listing__country_latest + FROM ( + -- Read Elements From Semantic Model 'listings_latest' + SELECT + 1 AS listings + , listings_latest_src_10004.capacity AS largest_listing + , listings_latest_src_10004.capacity AS smallest_listing + , DATE_TRUNC('day', listings_latest_src_10004.created_at) AS ds__day + , DATE_TRUNC('week', listings_latest_src_10004.created_at) AS ds__week + , DATE_TRUNC('month', listings_latest_src_10004.created_at) AS ds__month + , DATE_TRUNC('quarter', listings_latest_src_10004.created_at) AS ds__quarter + , DATE_TRUNC('year', listings_latest_src_10004.created_at) AS ds__year + , EXTRACT(year FROM listings_latest_src_10004.created_at) AS ds__extract_year + , EXTRACT(quarter FROM listings_latest_src_10004.created_at) AS ds__extract_quarter + , EXTRACT(month FROM listings_latest_src_10004.created_at) AS ds__extract_month + , EXTRACT(day FROM listings_latest_src_10004.created_at) AS ds__extract_day + , EXTRACT(isodow FROM listings_latest_src_10004.created_at) AS ds__extract_dow + , EXTRACT(doy FROM listings_latest_src_10004.created_at) AS ds__extract_doy + , DATE_TRUNC('day', listings_latest_src_10004.created_at) AS created_at__day + , DATE_TRUNC('week', listings_latest_src_10004.created_at) AS created_at__week + , DATE_TRUNC('month', listings_latest_src_10004.created_at) AS created_at__month + , DATE_TRUNC('quarter', listings_latest_src_10004.created_at) AS created_at__quarter + , DATE_TRUNC('year', listings_latest_src_10004.created_at) AS created_at__year + , EXTRACT(year FROM listings_latest_src_10004.created_at) AS created_at__extract_year + , EXTRACT(quarter FROM listings_latest_src_10004.created_at) AS created_at__extract_quarter + , EXTRACT(month FROM listings_latest_src_10004.created_at) AS created_at__extract_month + , EXTRACT(day FROM listings_latest_src_10004.created_at) AS created_at__extract_day + , EXTRACT(isodow FROM listings_latest_src_10004.created_at) AS created_at__extract_dow + , EXTRACT(doy FROM listings_latest_src_10004.created_at) AS created_at__extract_doy + , listings_latest_src_10004.country AS country_latest + , listings_latest_src_10004.is_lux AS is_lux_latest + , listings_latest_src_10004.capacity AS capacity_latest + , DATE_TRUNC('day', listings_latest_src_10004.created_at) AS listing__ds__day + , DATE_TRUNC('week', listings_latest_src_10004.created_at) AS listing__ds__week + , DATE_TRUNC('month', listings_latest_src_10004.created_at) AS listing__ds__month + , DATE_TRUNC('quarter', listings_latest_src_10004.created_at) AS listing__ds__quarter + , DATE_TRUNC('year', listings_latest_src_10004.created_at) AS listing__ds__year + , EXTRACT(year FROM listings_latest_src_10004.created_at) AS listing__ds__extract_year + , EXTRACT(quarter FROM listings_latest_src_10004.created_at) AS listing__ds__extract_quarter + , EXTRACT(month FROM listings_latest_src_10004.created_at) AS listing__ds__extract_month + , EXTRACT(day FROM listings_latest_src_10004.created_at) AS listing__ds__extract_day + , EXTRACT(isodow FROM listings_latest_src_10004.created_at) AS listing__ds__extract_dow + , EXTRACT(doy FROM listings_latest_src_10004.created_at) AS listing__ds__extract_doy + , DATE_TRUNC('day', listings_latest_src_10004.created_at) AS listing__created_at__day + , DATE_TRUNC('week', listings_latest_src_10004.created_at) AS listing__created_at__week + , DATE_TRUNC('month', listings_latest_src_10004.created_at) AS listing__created_at__month + , DATE_TRUNC('quarter', listings_latest_src_10004.created_at) AS listing__created_at__quarter + , DATE_TRUNC('year', listings_latest_src_10004.created_at) AS listing__created_at__year + , EXTRACT(year FROM listings_latest_src_10004.created_at) AS listing__created_at__extract_year + , EXTRACT(quarter FROM listings_latest_src_10004.created_at) AS listing__created_at__extract_quarter + , EXTRACT(month FROM listings_latest_src_10004.created_at) AS listing__created_at__extract_month + , EXTRACT(day FROM listings_latest_src_10004.created_at) AS listing__created_at__extract_day + , EXTRACT(isodow FROM listings_latest_src_10004.created_at) AS listing__created_at__extract_dow + , EXTRACT(doy FROM listings_latest_src_10004.created_at) AS listing__created_at__extract_doy + , listings_latest_src_10004.country AS listing__country_latest + , listings_latest_src_10004.is_lux AS listing__is_lux_latest + , listings_latest_src_10004.capacity AS listing__capacity_latest + , listings_latest_src_10004.listing_id AS listing + , listings_latest_src_10004.user_id AS user + , listings_latest_src_10004.user_id AS listing__user + FROM ***************************.dim_listings_latest listings_latest_src_10004 + ) subq_0 + GROUP BY + subq_0.listing__country_latest +) subq_1 diff --git a/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_categorical__plan0_optimized.sql b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_categorical__plan0_optimized.sql new file mode 100644 index 0000000000..c0e3a320a8 --- /dev/null +++ b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_categorical__plan0_optimized.sql @@ -0,0 +1,14 @@ +-- Calculate min and max +SELECT + MIN(listing__country_latest) AS min + , MAX(listing__country_latest) AS max +FROM ( + -- Read Elements From Semantic Model 'listings_latest' + -- Pass Only Elements: + -- ['listing__country_latest'] + SELECT + country AS listing__country_latest + FROM ***************************.dim_listings_latest listings_latest_src_10004 + GROUP BY + country +) subq_3 diff --git a/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time__plan0.sql b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time__plan0.sql new file mode 100644 index 0000000000..d56eaefcb1 --- /dev/null +++ b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time__plan0.sql @@ -0,0 +1,105 @@ +-- Calculate min and max +SELECT + MIN(booking__paid_at__day) AS min + , MAX(booking__paid_at__day) AS max +FROM ( + -- Pass Only Elements: + -- ['booking__paid_at__day'] + SELECT + subq_0.booking__paid_at__day + 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_10001.booking_value + , bookings_source_src_10001.booking_value AS max_booking_value + , bookings_source_src_10001.booking_value AS min_booking_value + , bookings_source_src_10001.guest_id AS bookers + , bookings_source_src_10001.booking_value AS average_booking_value + , bookings_source_src_10001.booking_value AS booking_payments + , CASE WHEN referrer_id IS NOT NULL THEN 1 ELSE 0 END AS referred_bookings + , bookings_source_src_10001.booking_value AS median_booking_value + , bookings_source_src_10001.booking_value AS booking_value_p99 + , bookings_source_src_10001.booking_value AS discrete_booking_value_p99 + , bookings_source_src_10001.booking_value AS approximate_continuous_booking_value_p99 + , bookings_source_src_10001.booking_value AS approximate_discrete_booking_value_p99 + , bookings_source_src_10001.is_instant + , DATE_TRUNC('day', bookings_source_src_10001.ds) AS ds__day + , DATE_TRUNC('week', bookings_source_src_10001.ds) AS ds__week + , DATE_TRUNC('month', bookings_source_src_10001.ds) AS ds__month + , DATE_TRUNC('quarter', bookings_source_src_10001.ds) AS ds__quarter + , DATE_TRUNC('year', bookings_source_src_10001.ds) AS ds__year + , EXTRACT(year FROM bookings_source_src_10001.ds) AS ds__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.ds) AS ds__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.ds) AS ds__extract_month + , EXTRACT(day FROM bookings_source_src_10001.ds) AS ds__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.ds) AS ds__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.ds) AS ds__extract_doy + , DATE_TRUNC('day', bookings_source_src_10001.ds_partitioned) AS ds_partitioned__day + , DATE_TRUNC('week', bookings_source_src_10001.ds_partitioned) AS ds_partitioned__week + , DATE_TRUNC('month', bookings_source_src_10001.ds_partitioned) AS ds_partitioned__month + , DATE_TRUNC('quarter', bookings_source_src_10001.ds_partitioned) AS ds_partitioned__quarter + , DATE_TRUNC('year', bookings_source_src_10001.ds_partitioned) AS ds_partitioned__year + , EXTRACT(year FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_month + , EXTRACT(day FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_doy + , DATE_TRUNC('day', bookings_source_src_10001.paid_at) AS paid_at__day + , DATE_TRUNC('week', bookings_source_src_10001.paid_at) AS paid_at__week + , DATE_TRUNC('month', bookings_source_src_10001.paid_at) AS paid_at__month + , DATE_TRUNC('quarter', bookings_source_src_10001.paid_at) AS paid_at__quarter + , DATE_TRUNC('year', bookings_source_src_10001.paid_at) AS paid_at__year + , EXTRACT(year FROM bookings_source_src_10001.paid_at) AS paid_at__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.paid_at) AS paid_at__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.paid_at) AS paid_at__extract_month + , EXTRACT(day FROM bookings_source_src_10001.paid_at) AS paid_at__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.paid_at) AS paid_at__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.paid_at) AS paid_at__extract_doy + , bookings_source_src_10001.is_instant AS booking__is_instant + , DATE_TRUNC('day', bookings_source_src_10001.ds) AS booking__ds__day + , DATE_TRUNC('week', bookings_source_src_10001.ds) AS booking__ds__week + , DATE_TRUNC('month', bookings_source_src_10001.ds) AS booking__ds__month + , DATE_TRUNC('quarter', bookings_source_src_10001.ds) AS booking__ds__quarter + , DATE_TRUNC('year', bookings_source_src_10001.ds) AS booking__ds__year + , EXTRACT(year FROM bookings_source_src_10001.ds) AS booking__ds__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.ds) AS booking__ds__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.ds) AS booking__ds__extract_month + , EXTRACT(day FROM bookings_source_src_10001.ds) AS booking__ds__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.ds) AS booking__ds__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.ds) AS booking__ds__extract_doy + , DATE_TRUNC('day', bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__day + , DATE_TRUNC('week', bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__week + , DATE_TRUNC('month', bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__month + , DATE_TRUNC('quarter', bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__quarter + , DATE_TRUNC('year', bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__year + , EXTRACT(year FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_month + , EXTRACT(day FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_doy + , DATE_TRUNC('day', bookings_source_src_10001.paid_at) AS booking__paid_at__day + , DATE_TRUNC('week', bookings_source_src_10001.paid_at) AS booking__paid_at__week + , DATE_TRUNC('month', bookings_source_src_10001.paid_at) AS booking__paid_at__month + , DATE_TRUNC('quarter', bookings_source_src_10001.paid_at) AS booking__paid_at__quarter + , DATE_TRUNC('year', bookings_source_src_10001.paid_at) AS booking__paid_at__year + , EXTRACT(year FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_month + , EXTRACT(day FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_doy + , bookings_source_src_10001.listing_id AS listing + , bookings_source_src_10001.guest_id AS guest + , bookings_source_src_10001.host_id AS host + , bookings_source_src_10001.listing_id AS booking__listing + , bookings_source_src_10001.guest_id AS booking__guest + , bookings_source_src_10001.host_id AS booking__host + FROM ***************************.fct_bookings bookings_source_src_10001 + ) subq_0 + GROUP BY + subq_0.booking__paid_at__day +) subq_1 diff --git a/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time__plan0_optimized.sql b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time__plan0_optimized.sql new file mode 100644 index 0000000000..ae6233abe1 --- /dev/null +++ b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time__plan0_optimized.sql @@ -0,0 +1,14 @@ +-- Calculate min and max +SELECT + MIN(booking__paid_at__day) AS min + , MAX(booking__paid_at__day) AS max +FROM ( + -- Read Elements From Semantic Model 'bookings_source' + -- Pass Only Elements: + -- ['booking__paid_at__day'] + SELECT + DATE_TRUNC('day', paid_at) AS booking__paid_at__day + FROM ***************************.fct_bookings bookings_source_src_10001 + GROUP BY + DATE_TRUNC('day', paid_at) +) subq_3 diff --git a/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time_quarter__plan0.sql b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time_quarter__plan0.sql new file mode 100644 index 0000000000..abbdce9ea4 --- /dev/null +++ b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time_quarter__plan0.sql @@ -0,0 +1,105 @@ +-- Calculate min and max +SELECT + MIN(booking__paid_at__quarter) AS min + , MAX(booking__paid_at__quarter) AS max +FROM ( + -- Pass Only Elements: + -- ['booking__paid_at__quarter'] + SELECT + subq_0.booking__paid_at__quarter + 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_10001.booking_value + , bookings_source_src_10001.booking_value AS max_booking_value + , bookings_source_src_10001.booking_value AS min_booking_value + , bookings_source_src_10001.guest_id AS bookers + , bookings_source_src_10001.booking_value AS average_booking_value + , bookings_source_src_10001.booking_value AS booking_payments + , CASE WHEN referrer_id IS NOT NULL THEN 1 ELSE 0 END AS referred_bookings + , bookings_source_src_10001.booking_value AS median_booking_value + , bookings_source_src_10001.booking_value AS booking_value_p99 + , bookings_source_src_10001.booking_value AS discrete_booking_value_p99 + , bookings_source_src_10001.booking_value AS approximate_continuous_booking_value_p99 + , bookings_source_src_10001.booking_value AS approximate_discrete_booking_value_p99 + , bookings_source_src_10001.is_instant + , DATE_TRUNC('day', bookings_source_src_10001.ds) AS ds__day + , DATE_TRUNC('week', bookings_source_src_10001.ds) AS ds__week + , DATE_TRUNC('month', bookings_source_src_10001.ds) AS ds__month + , DATE_TRUNC('quarter', bookings_source_src_10001.ds) AS ds__quarter + , DATE_TRUNC('year', bookings_source_src_10001.ds) AS ds__year + , EXTRACT(year FROM bookings_source_src_10001.ds) AS ds__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.ds) AS ds__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.ds) AS ds__extract_month + , EXTRACT(day FROM bookings_source_src_10001.ds) AS ds__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.ds) AS ds__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.ds) AS ds__extract_doy + , DATE_TRUNC('day', bookings_source_src_10001.ds_partitioned) AS ds_partitioned__day + , DATE_TRUNC('week', bookings_source_src_10001.ds_partitioned) AS ds_partitioned__week + , DATE_TRUNC('month', bookings_source_src_10001.ds_partitioned) AS ds_partitioned__month + , DATE_TRUNC('quarter', bookings_source_src_10001.ds_partitioned) AS ds_partitioned__quarter + , DATE_TRUNC('year', bookings_source_src_10001.ds_partitioned) AS ds_partitioned__year + , EXTRACT(year FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_month + , EXTRACT(day FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.ds_partitioned) AS ds_partitioned__extract_doy + , DATE_TRUNC('day', bookings_source_src_10001.paid_at) AS paid_at__day + , DATE_TRUNC('week', bookings_source_src_10001.paid_at) AS paid_at__week + , DATE_TRUNC('month', bookings_source_src_10001.paid_at) AS paid_at__month + , DATE_TRUNC('quarter', bookings_source_src_10001.paid_at) AS paid_at__quarter + , DATE_TRUNC('year', bookings_source_src_10001.paid_at) AS paid_at__year + , EXTRACT(year FROM bookings_source_src_10001.paid_at) AS paid_at__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.paid_at) AS paid_at__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.paid_at) AS paid_at__extract_month + , EXTRACT(day FROM bookings_source_src_10001.paid_at) AS paid_at__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.paid_at) AS paid_at__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.paid_at) AS paid_at__extract_doy + , bookings_source_src_10001.is_instant AS booking__is_instant + , DATE_TRUNC('day', bookings_source_src_10001.ds) AS booking__ds__day + , DATE_TRUNC('week', bookings_source_src_10001.ds) AS booking__ds__week + , DATE_TRUNC('month', bookings_source_src_10001.ds) AS booking__ds__month + , DATE_TRUNC('quarter', bookings_source_src_10001.ds) AS booking__ds__quarter + , DATE_TRUNC('year', bookings_source_src_10001.ds) AS booking__ds__year + , EXTRACT(year FROM bookings_source_src_10001.ds) AS booking__ds__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.ds) AS booking__ds__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.ds) AS booking__ds__extract_month + , EXTRACT(day FROM bookings_source_src_10001.ds) AS booking__ds__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.ds) AS booking__ds__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.ds) AS booking__ds__extract_doy + , DATE_TRUNC('day', bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__day + , DATE_TRUNC('week', bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__week + , DATE_TRUNC('month', bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__month + , DATE_TRUNC('quarter', bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__quarter + , DATE_TRUNC('year', bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__year + , EXTRACT(year FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_month + , EXTRACT(day FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.ds_partitioned) AS booking__ds_partitioned__extract_doy + , DATE_TRUNC('day', bookings_source_src_10001.paid_at) AS booking__paid_at__day + , DATE_TRUNC('week', bookings_source_src_10001.paid_at) AS booking__paid_at__week + , DATE_TRUNC('month', bookings_source_src_10001.paid_at) AS booking__paid_at__month + , DATE_TRUNC('quarter', bookings_source_src_10001.paid_at) AS booking__paid_at__quarter + , DATE_TRUNC('year', bookings_source_src_10001.paid_at) AS booking__paid_at__year + , EXTRACT(year FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_year + , EXTRACT(quarter FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_quarter + , EXTRACT(month FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_month + , EXTRACT(day FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_day + , EXTRACT(isodow FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_dow + , EXTRACT(doy FROM bookings_source_src_10001.paid_at) AS booking__paid_at__extract_doy + , bookings_source_src_10001.listing_id AS listing + , bookings_source_src_10001.guest_id AS guest + , bookings_source_src_10001.host_id AS host + , bookings_source_src_10001.listing_id AS booking__listing + , bookings_source_src_10001.guest_id AS booking__guest + , bookings_source_src_10001.host_id AS booking__host + FROM ***************************.fct_bookings bookings_source_src_10001 + ) subq_0 + GROUP BY + subq_0.booking__paid_at__quarter +) subq_1 diff --git a/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time_quarter__plan0_optimized.sql b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time_quarter__plan0_optimized.sql new file mode 100644 index 0000000000..694eb4fa91 --- /dev/null +++ b/metricflow/test/snapshots/test_query_rendering.py/SqlQueryPlan/DuckDB/test_min_max_only_time_quarter__plan0_optimized.sql @@ -0,0 +1,14 @@ +-- Calculate min and max +SELECT + MIN(booking__paid_at__quarter) AS min + , MAX(booking__paid_at__quarter) AS max +FROM ( + -- Read Elements From Semantic Model 'bookings_source' + -- Pass Only Elements: + -- ['booking__paid_at__quarter'] + SELECT + DATE_TRUNC('quarter', paid_at) AS booking__paid_at__quarter + FROM ***************************.fct_bookings bookings_source_src_10001 + GROUP BY + DATE_TRUNC('quarter', paid_at) +) subq_3