Skip to content

Commit

Permalink
Add SQL rendering tests for querying a metric with a custom grain filter
Browse files Browse the repository at this point in the history
  • Loading branch information
courtneyholcomb committed Sep 23, 2024
1 parent a398924 commit e528b5e
Show file tree
Hide file tree
Showing 30 changed files with 3,601 additions and 8 deletions.
16 changes: 8 additions & 8 deletions metricflow/plan_conversion/dataflow_to_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -1087,9 +1087,9 @@ def visit_metric_time_dimension_transform_node(self, node: MetricTimeDimensionTr
spec=metric_time_dimension_spec,
)
)
output_column_to_input_column[metric_time_dimension_column_association.column_name] = (
matching_time_dimension_instance.associated_column.column_name
)
output_column_to_input_column[
metric_time_dimension_column_association.column_name
] = matching_time_dimension_instance.associated_column.column_name

output_instance_set = InstanceSet(
measure_instances=tuple(output_measure_instances),
Expand Down Expand Up @@ -1324,11 +1324,11 @@ def visit_join_to_time_spine_node(self, node: JoinToTimeSpineNode) -> SqlDataSet
and len(time_spine_dataset.checked_sql_select_node.select_columns) == 1
), "Time spine dataset not configured properly. Expected exactly one column."
original_time_spine_dim_instance = time_spine_dataset.instance_set.time_dimension_instances[0]
time_spine_column_select_expr: Union[SqlColumnReferenceExpression, SqlDateTruncExpression] = (
SqlColumnReferenceExpression.create(
SqlColumnReference(
table_alias=time_spine_alias, column_name=original_time_spine_dim_instance.spec.qualified_name
)
time_spine_column_select_expr: Union[
SqlColumnReferenceExpression, SqlDateTruncExpression
] = SqlColumnReferenceExpression.create(
SqlColumnReference(
table_alias=time_spine_alias, column_name=original_time_spine_dim_instance.spec.qualified_name
)
)

Expand Down
58 changes: 58 additions & 0 deletions tests_metricflow/query_rendering/test_custom_granularity.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

import pytest
from _pytest.fixtures import FixtureRequest
from dbt_semantic_interfaces.implementations.filters.where_filter import PydanticWhereFilter
from dbt_semantic_interfaces.references import EntityReference
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity
from metricflow_semantics.query.query_parser import MetricFlowQueryParser
from metricflow_semantics.specs.metric_spec import MetricSpec
from metricflow_semantics.specs.query_spec import MetricFlowQuerySpec
from metricflow_semantics.specs.time_dimension_spec import TimeDimensionSpec
Expand Down Expand Up @@ -267,3 +269,59 @@ def test_simple_metric_with_custom_granularity_and_join( # noqa: D103
dataflow_plan_builder=dataflow_plan_builder,
query_spec=query_spec,
)


# TODO: optimizer - could collaps subquery
@pytest.mark.sql_engine_snapshot
def test_simple_metric_with_custom_granularity_filter(
request: FixtureRequest,
mf_test_configuration: MetricFlowTestConfiguration,
dataflow_plan_builder: DataflowPlanBuilder,
dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter,
sql_client: SqlClient,
query_parser: MetricFlowQueryParser,
) -> None:
"""Simple metric queried with a filter on a custom grain, where that grain is not used in the group by."""
query_spec = query_parser.parse_and_validate_query(
metric_names=("bookings",),
where_constraint=PydanticWhereFilter(
where_sql_template=("{{ TimeDimension('metric_time', 'martian_day') }} = '2020-01-01'")
),
).query_spec

render_and_check(
request=request,
mf_test_configuration=mf_test_configuration,
dataflow_to_sql_converter=dataflow_to_sql_converter,
sql_client=sql_client,
dataflow_plan_builder=dataflow_plan_builder,
query_spec=query_spec,
)


@pytest.mark.sql_engine_snapshot
def test_simple_metric_with_custom_granularity_in_filter_and_group_by(
request: FixtureRequest,
mf_test_configuration: MetricFlowTestConfiguration,
dataflow_plan_builder: DataflowPlanBuilder,
dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter,
sql_client: SqlClient,
query_parser: MetricFlowQueryParser,
) -> None:
"""Simple metric queried with a filter on a custom grain, where that grain is also used in the group by."""
query_spec = query_parser.parse_and_validate_query(
metric_names=("bookings",),
group_by_names=("metric_time__martian_day",),
where_constraint=PydanticWhereFilter(
where_sql_template=("{{ TimeDimension('metric_time', 'martian_day') }} = '2020-01-01'")
),
).query_spec

render_and_check(
request=request,
mf_test_configuration=mf_test_configuration,
dataflow_to_sql_converter=dataflow_to_sql_converter,
sql_client=sql_client,
dataflow_plan_builder=dataflow_plan_builder,
query_spec=query_spec,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
-- Compute Metrics via Expressions
SELECT
subq_6.bookings
FROM (
-- Aggregate Measures
SELECT
SUM(subq_5.bookings) AS bookings
FROM (
-- Pass Only Elements: ['bookings',]
SELECT
subq_4.bookings
FROM (
-- Constrain Output with WHERE
SELECT
subq_3.metric_time__martian_day
, subq_3.bookings
FROM (
-- Join to Custom Granularity Dataset
-- Pass Only Elements: ['bookings', 'metric_time__day']
SELECT
subq_1.bookings AS bookings
, subq_2.martian_day AS metric_time__martian_day
FROM (
-- 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
, DATETIME_TRUNC(bookings_source_src_28000.ds, day) AS ds__day
, DATETIME_TRUNC(bookings_source_src_28000.ds, isoweek) AS ds__week
, DATETIME_TRUNC(bookings_source_src_28000.ds, month) AS ds__month
, DATETIME_TRUNC(bookings_source_src_28000.ds, quarter) AS ds__quarter
, DATETIME_TRUNC(bookings_source_src_28000.ds, year) 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
, IF(EXTRACT(dayofweek FROM bookings_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM bookings_source_src_28000.ds) - 1) AS ds__extract_dow
, EXTRACT(dayofyear FROM bookings_source_src_28000.ds) AS ds__extract_doy
, DATETIME_TRUNC(bookings_source_src_28000.ds_partitioned, day) AS ds_partitioned__day
, DATETIME_TRUNC(bookings_source_src_28000.ds_partitioned, isoweek) AS ds_partitioned__week
, DATETIME_TRUNC(bookings_source_src_28000.ds_partitioned, month) AS ds_partitioned__month
, DATETIME_TRUNC(bookings_source_src_28000.ds_partitioned, quarter) AS ds_partitioned__quarter
, DATETIME_TRUNC(bookings_source_src_28000.ds_partitioned, year) 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
, IF(EXTRACT(dayofweek FROM bookings_source_src_28000.ds_partitioned) = 1, 7, EXTRACT(dayofweek FROM bookings_source_src_28000.ds_partitioned) - 1) AS ds_partitioned__extract_dow
, EXTRACT(dayofyear FROM bookings_source_src_28000.ds_partitioned) AS ds_partitioned__extract_doy
, DATETIME_TRUNC(bookings_source_src_28000.paid_at, day) AS paid_at__day
, DATETIME_TRUNC(bookings_source_src_28000.paid_at, isoweek) AS paid_at__week
, DATETIME_TRUNC(bookings_source_src_28000.paid_at, month) AS paid_at__month
, DATETIME_TRUNC(bookings_source_src_28000.paid_at, quarter) AS paid_at__quarter
, DATETIME_TRUNC(bookings_source_src_28000.paid_at, year) 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
, IF(EXTRACT(dayofweek FROM bookings_source_src_28000.paid_at) = 1, 7, EXTRACT(dayofweek FROM bookings_source_src_28000.paid_at) - 1) AS paid_at__extract_dow
, EXTRACT(dayofyear FROM bookings_source_src_28000.paid_at) AS paid_at__extract_doy
, bookings_source_src_28000.is_instant AS booking__is_instant
, DATETIME_TRUNC(bookings_source_src_28000.ds, day) AS booking__ds__day
, DATETIME_TRUNC(bookings_source_src_28000.ds, isoweek) AS booking__ds__week
, DATETIME_TRUNC(bookings_source_src_28000.ds, month) AS booking__ds__month
, DATETIME_TRUNC(bookings_source_src_28000.ds, quarter) AS booking__ds__quarter
, DATETIME_TRUNC(bookings_source_src_28000.ds, year) 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
, IF(EXTRACT(dayofweek FROM bookings_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM bookings_source_src_28000.ds) - 1) AS booking__ds__extract_dow
, EXTRACT(dayofyear FROM bookings_source_src_28000.ds) AS booking__ds__extract_doy
, DATETIME_TRUNC(bookings_source_src_28000.ds_partitioned, day) AS booking__ds_partitioned__day
, DATETIME_TRUNC(bookings_source_src_28000.ds_partitioned, isoweek) AS booking__ds_partitioned__week
, DATETIME_TRUNC(bookings_source_src_28000.ds_partitioned, month) AS booking__ds_partitioned__month
, DATETIME_TRUNC(bookings_source_src_28000.ds_partitioned, quarter) AS booking__ds_partitioned__quarter
, DATETIME_TRUNC(bookings_source_src_28000.ds_partitioned, year) 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
, IF(EXTRACT(dayofweek FROM bookings_source_src_28000.ds_partitioned) = 1, 7, EXTRACT(dayofweek FROM bookings_source_src_28000.ds_partitioned) - 1) AS booking__ds_partitioned__extract_dow
, EXTRACT(dayofyear FROM bookings_source_src_28000.ds_partitioned) AS booking__ds_partitioned__extract_doy
, DATETIME_TRUNC(bookings_source_src_28000.paid_at, day) AS booking__paid_at__day
, DATETIME_TRUNC(bookings_source_src_28000.paid_at, isoweek) AS booking__paid_at__week
, DATETIME_TRUNC(bookings_source_src_28000.paid_at, month) AS booking__paid_at__month
, DATETIME_TRUNC(bookings_source_src_28000.paid_at, quarter) AS booking__paid_at__quarter
, DATETIME_TRUNC(bookings_source_src_28000.paid_at, year) 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
, IF(EXTRACT(dayofweek FROM bookings_source_src_28000.paid_at) = 1, 7, EXTRACT(dayofweek FROM bookings_source_src_28000.paid_at) - 1) AS booking__paid_at__extract_dow
, EXTRACT(dayofyear 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
LEFT OUTER JOIN
***************************.mf_time_spine subq_2
ON
subq_1.metric_time__day = subq_2.ds
) subq_3
WHERE metric_time__martian_day = '2020-01-01'
) subq_4
) subq_5
) subq_6
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
-- Constrain Output with WHERE
-- Pass Only Elements: ['bookings',]
-- Aggregate Measures
-- Compute Metrics via Expressions
SELECT
SUM(bookings) AS bookings
FROM (
-- Join to Custom Granularity Dataset
-- Pass Only Elements: ['bookings', 'metric_time__day']
SELECT
subq_8.bookings AS bookings
, subq_9.martian_day AS metric_time__martian_day
FROM (
-- Read Elements From Semantic Model 'bookings_source'
-- Metric Time Dimension 'ds'
SELECT
DATETIME_TRUNC(ds, day) AS metric_time__day
, 1 AS bookings
FROM ***************************.fct_bookings bookings_source_src_28000
) subq_8
LEFT OUTER JOIN
***************************.mf_time_spine subq_9
ON
subq_8.metric_time__day = subq_9.ds
) subq_10
WHERE metric_time__martian_day = '2020-01-01'
Loading

0 comments on commit e528b5e

Please sign in to comment.