From c611b44d26eb219853e37f49b5d5b38553c81cce Mon Sep 17 00:00:00 2001 From: Courtney Holcomb Date: Tue, 29 Oct 2024 18:16:27 -0700 Subject: [PATCH] Support conversion metrics with custom grain (#1475) Support for conversion metrics used with custom granularities in the group by or the where filter. --- .../unreleased/Features-20241023-161720.yaml | 6 + .../specs/linkable_spec_set.py | 10 + .../metricflow_semantics/specs/spec_set.py | 18 +- .../dataflow/builder/dataflow_plan_builder.py | 43 +- .../dataflow/builder/source_node_recipe.py | 5 +- metricflow/plan_conversion/dataflow_to_sql.py | 2 +- .../test_cases/itest_granularity.yaml | 382 ++++++++++++++ .../test_custom_granularity.py | 77 +++ ..._metric_with_custom_granularity__plan0.sql | 422 ++++++++++++++++ ...th_custom_granularity__plan0_optimized.sql | 139 +++++ ..._with_custom_granularity_filter__plan0.sql | 477 ++++++++++++++++++ ...om_granularity_filter__plan0_optimized.sql | 156 ++++++ ...nularity_filter_not_in_group_by__plan0.sql | 457 +++++++++++++++++ ...ilter_not_in_group_by__plan0_optimized.sql | 138 +++++ ..._metric_with_custom_granularity__plan0.sql | 422 ++++++++++++++++ ...th_custom_granularity__plan0_optimized.sql | 139 +++++ ..._with_custom_granularity_filter__plan0.sql | 477 ++++++++++++++++++ ...om_granularity_filter__plan0_optimized.sql | 156 ++++++ ...nularity_filter_not_in_group_by__plan0.sql | 457 +++++++++++++++++ ...ilter_not_in_group_by__plan0_optimized.sql | 138 +++++ ..._metric_with_custom_granularity__plan0.sql | 422 ++++++++++++++++ ...th_custom_granularity__plan0_optimized.sql | 139 +++++ ..._with_custom_granularity_filter__plan0.sql | 477 ++++++++++++++++++ ...om_granularity_filter__plan0_optimized.sql | 156 ++++++ ...nularity_filter_not_in_group_by__plan0.sql | 457 +++++++++++++++++ ...ilter_not_in_group_by__plan0_optimized.sql | 138 +++++ ..._metric_with_custom_granularity__plan0.sql | 422 ++++++++++++++++ ...th_custom_granularity__plan0_optimized.sql | 139 +++++ ..._with_custom_granularity_filter__plan0.sql | 477 ++++++++++++++++++ ...om_granularity_filter__plan0_optimized.sql | 156 ++++++ ...nularity_filter_not_in_group_by__plan0.sql | 457 +++++++++++++++++ ...ilter_not_in_group_by__plan0_optimized.sql | 138 +++++ ..._metric_with_custom_granularity__plan0.sql | 422 ++++++++++++++++ ...th_custom_granularity__plan0_optimized.sql | 139 +++++ ..._with_custom_granularity_filter__plan0.sql | 477 ++++++++++++++++++ ...om_granularity_filter__plan0_optimized.sql | 156 ++++++ ...nularity_filter_not_in_group_by__plan0.sql | 457 +++++++++++++++++ ...ilter_not_in_group_by__plan0_optimized.sql | 138 +++++ ..._metric_with_custom_granularity__plan0.sql | 422 ++++++++++++++++ ...th_custom_granularity__plan0_optimized.sql | 139 +++++ ..._with_custom_granularity_filter__plan0.sql | 477 ++++++++++++++++++ ...om_granularity_filter__plan0_optimized.sql | 156 ++++++ ...nularity_filter_not_in_group_by__plan0.sql | 457 +++++++++++++++++ ...ilter_not_in_group_by__plan0_optimized.sql | 138 +++++ ..._metric_with_custom_granularity__plan0.sql | 422 ++++++++++++++++ ...th_custom_granularity__plan0_optimized.sql | 139 +++++ ..._with_custom_granularity_filter__plan0.sql | 477 ++++++++++++++++++ ...om_granularity_filter__plan0_optimized.sql | 156 ++++++ ...nularity_filter_not_in_group_by__plan0.sql | 457 +++++++++++++++++ ...ilter_not_in_group_by__plan0_optimized.sql | 138 +++++ 50 files changed, 13034 insertions(+), 32 deletions(-) create mode 100644 .changes/unreleased/Features-20241023-161720.yaml create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql create mode 100644 tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql diff --git a/.changes/unreleased/Features-20241023-161720.yaml b/.changes/unreleased/Features-20241023-161720.yaml new file mode 100644 index 0000000000..ae0a490ef4 --- /dev/null +++ b/.changes/unreleased/Features-20241023-161720.yaml @@ -0,0 +1,6 @@ +kind: Features +body: Support conversion metrics queried with custom granularities. +time: 2024-10-23T16:17:20.92419-07:00 +custom: + Author: courtneyholcomb + Issue: "1475" diff --git a/metricflow-semantics/metricflow_semantics/specs/linkable_spec_set.py b/metricflow-semantics/metricflow_semantics/specs/linkable_spec_set.py index 41d3a9ea32..4f57921d94 100644 --- a/metricflow-semantics/metricflow_semantics/specs/linkable_spec_set.py +++ b/metricflow-semantics/metricflow_semantics/specs/linkable_spec_set.py @@ -15,6 +15,7 @@ from metricflow_semantics.specs.entity_spec import EntitySpec from metricflow_semantics.specs.group_by_metric_spec import GroupByMetricSpec from metricflow_semantics.specs.instance_spec import InstanceSpecVisitor, LinkableInstanceSpec +from metricflow_semantics.specs.spec_set import InstanceSpecSet from metricflow_semantics.specs.time_dimension_spec import TimeDimensionSpec if typing.TYPE_CHECKING: @@ -154,6 +155,15 @@ def difference(self, other: LinkableSpecSet) -> LinkableSpecSet: # noqa: D102 def create_from_specs(specs: Sequence[LinkableInstanceSpec]) -> LinkableSpecSet: # noqa: D102 return _group_specs_by_type(specs) + @property + def as_instance_spec_set(self) -> InstanceSpecSet: # noqa: D102 + return InstanceSpecSet( + dimension_specs=self.dimension_specs, + entity_specs=self.entity_specs, + time_dimension_specs=self.time_dimension_specs, + group_by_metric_specs=self.group_by_metric_specs, + ) + @dataclass class _GroupSpecByTypeVisitor(InstanceSpecVisitor[None]): diff --git a/metricflow-semantics/metricflow_semantics/specs/spec_set.py b/metricflow-semantics/metricflow_semantics/specs/spec_set.py index 0c87fc0872..f115932a83 100644 --- a/metricflow-semantics/metricflow_semantics/specs/spec_set.py +++ b/metricflow-semantics/metricflow_semantics/specs/spec_set.py @@ -4,20 +4,22 @@ import itertools from abc import ABC, abstractmethod from dataclasses import dataclass -from typing import Generic, List, Sequence, Tuple, TypeVar +from typing import TYPE_CHECKING, Generic, List, Sequence, Tuple, TypeVar from dbt_semantic_interfaces.dataclass_serialization import SerializableDataclass from typing_extensions import override from metricflow_semantics.collection_helpers.merger import Mergeable -from metricflow_semantics.specs.dimension_spec import DimensionSpec -from metricflow_semantics.specs.entity_spec import EntitySpec -from metricflow_semantics.specs.group_by_metric_spec import GroupByMetricSpec from metricflow_semantics.specs.instance_spec import InstanceSpec, InstanceSpecVisitor, LinkableInstanceSpec -from metricflow_semantics.specs.measure_spec import MeasureSpec -from metricflow_semantics.specs.metadata_spec import MetadataSpec -from metricflow_semantics.specs.metric_spec import MetricSpec -from metricflow_semantics.specs.time_dimension_spec import TimeDimensionSpec + +if TYPE_CHECKING: + from metricflow_semantics.specs.dimension_spec import DimensionSpec + from metricflow_semantics.specs.entity_spec import EntitySpec + from metricflow_semantics.specs.group_by_metric_spec import GroupByMetricSpec + from metricflow_semantics.specs.measure_spec import MeasureSpec + from metricflow_semantics.specs.metadata_spec import MetadataSpec + from metricflow_semantics.specs.metric_spec import MetricSpec + from metricflow_semantics.specs.time_dimension_spec import TimeDimensionSpec @dataclass(frozen=True) diff --git a/metricflow/dataflow/builder/dataflow_plan_builder.py b/metricflow/dataflow/builder/dataflow_plan_builder.py index 81663bd69b..7f9d154880 100644 --- a/metricflow/dataflow/builder/dataflow_plan_builder.py +++ b/metricflow/dataflow/builder/dataflow_plan_builder.py @@ -315,7 +315,7 @@ def _build_aggregated_conversion_node( # Filter the source nodes with only the required specs needed for the calculation constant_property_specs = [] required_local_specs = [base_measure_spec.measure_spec, entity_spec, base_time_dimension_spec] + list( - base_measure_recipe.required_local_linkable_specs + base_measure_recipe.required_local_linkable_specs.as_tuple ) for constant_property in constant_properties or []: base_property_spec = self._semantic_model_lookup.get_element_spec_for_name(constant_property.base_property) @@ -333,6 +333,11 @@ def _build_aggregated_conversion_node( unaggregated_base_measure_node = JoinOnEntitiesNode.create( left_node=unaggregated_base_measure_node, join_targets=base_measure_recipe.join_targets ) + for time_dimension_spec in base_required_linkable_specs.time_dimension_specs: + if time_dimension_spec.time_granularity.is_custom_granularity: + unaggregated_base_measure_node = JoinToCustomGranularityNode.create( + parent_node=unaggregated_base_measure_node, time_dimension_spec=time_dimension_spec + ) if len(base_measure_spec.filter_spec_set.all_filter_specs) > 0: unaggregated_base_measure_node = WhereConstraintNode.create( parent_node=unaggregated_base_measure_node, @@ -341,7 +346,7 @@ def _build_aggregated_conversion_node( filtered_unaggregated_base_node = FilterElementsNode.create( parent_node=unaggregated_base_measure_node, include_specs=group_specs_by_type(required_local_specs) - .merge(InstanceSpecSet.create_from_specs(base_required_linkable_specs.as_tuple)) + .merge(base_required_linkable_specs.as_instance_spec_set) .dedupe(), ) @@ -361,11 +366,12 @@ def _build_aggregated_conversion_node( constant_properties=constant_property_specs, ) - # Aggregate the conversion events with the JoinConversionEventsNode as the source node + # Aggregate the conversion events with the JoinConversionEventsNode as the source node. recipe_with_join_conversion_source_node = SourceNodeRecipe( source_node=join_conversion_node, - required_local_linkable_specs=queried_linkable_specs.as_tuple, + required_local_linkable_specs=queried_linkable_specs, join_linkable_instances_recipes=(), + all_linkable_specs_required_for_source_nodes=queried_linkable_specs, ) # TODO: Refine conversion metric configuration to fit into the standard dataflow plan building model # In this case we override the measure recipe, which currently results in us bypassing predicate pushdown @@ -925,13 +931,11 @@ def _select_source_nodes_with_linkable_specs( selected_nodes: Dict[DataflowPlanNode, None] = {} # TODO: Add support for no-metrics queries for custom grains without a join (i.e., select directly from time spine). - linkable_specs_set_with_base_granularities = set(linkable_specs.as_tuple) + linkable_specs_set = set(linkable_specs.as_tuple) for source_node in source_nodes: output_spec_set = self._node_data_set_resolver.get_output_data_set(source_node).instance_set.spec_set all_linkable_specs_in_node = set(output_spec_set.linkable_specs) - requested_linkable_specs_in_node = linkable_specs_set_with_base_granularities.intersection( - all_linkable_specs_in_node - ) + requested_linkable_specs_in_node = linkable_specs_set.intersection(all_linkable_specs_in_node) if requested_linkable_specs_in_node: selected_nodes[source_node] = None @@ -998,13 +1002,7 @@ def _find_source_node_recipe(self, parameter_set: FindSourceNodeRecipeParameterS return result.source_node_recipe source_node_recipe = self._find_source_node_recipe_non_cached(parameter_set) self._cache.set_find_source_node_recipe_result(parameter_set, FindSourceNodeRecipeResult(source_node_recipe)) - if source_node_recipe is not None: - return SourceNodeRecipe( - source_node=source_node_recipe.source_node, - required_local_linkable_specs=source_node_recipe.required_local_linkable_specs, - join_linkable_instances_recipes=source_node_recipe.join_linkable_instances_recipes, - ) - return None + return source_node_recipe def _find_source_node_recipe_non_cached( self, parameter_set: FindSourceNodeRecipeParameterSet @@ -1234,13 +1232,14 @@ def _find_source_node_recipe_non_cached( ) return SourceNodeRecipe( source_node=node_with_lowest_cost_plan, - required_local_linkable_specs=( + required_local_linkable_specs=LinkableSpecSet.create_from_specs( evaluation.local_linkable_specs + required_local_entity_specs + required_local_dimension_specs + required_local_time_dimension_specs ), join_linkable_instances_recipes=node_to_evaluation[node_with_lowest_cost_plan].join_recipes, + all_linkable_specs_required_for_source_nodes=linkable_specs_to_satisfy, ) logger.error(LazyFormat(lambda: "No recipe could be constructed.")) @@ -1641,7 +1640,7 @@ def _build_aggregated_measure_from_measure_source_node( filtered_measure_source_node = FilterElementsNode.create( parent_node=join_to_time_spine_node or time_range_node or measure_recipe.source_node, include_specs=InstanceSpecSet(measure_specs=(measure_spec,)).merge( - group_specs_by_type(measure_recipe.required_local_linkable_specs), + measure_recipe.required_local_linkable_specs.as_instance_spec_set, ), ) @@ -1654,9 +1653,7 @@ def _build_aggregated_measure_from_measure_source_node( ) specs_to_keep_after_join = InstanceSpecSet(measure_specs=(measure_spec,)).merge( - InstanceSpecSet.create_from_specs( - required_linkable_specs.replace_custom_granularity_with_base_granularity().as_tuple - ), + InstanceSpecSet.create_from_specs(measure_recipe.all_linkable_specs_required_for_source_nodes.as_tuple), ) after_join_filtered_node = FilterElementsNode.create( @@ -1667,7 +1664,11 @@ def _build_aggregated_measure_from_measure_source_node( unaggregated_measure_node = filtered_measure_source_node for time_dimension_spec in required_linkable_specs.time_dimension_specs: - if time_dimension_spec.time_granularity.is_custom_granularity: + if ( + time_dimension_spec.time_granularity.is_custom_granularity + # If this is the second layer of aggregation for a conversion metric, we have already joined the custom granularity. + and time_dimension_spec not in measure_recipe.all_linkable_specs_required_for_source_nodes.as_tuple + ): unaggregated_measure_node = JoinToCustomGranularityNode.create( parent_node=unaggregated_measure_node, time_dimension_spec=time_dimension_spec ) diff --git a/metricflow/dataflow/builder/source_node_recipe.py b/metricflow/dataflow/builder/source_node_recipe.py index 59fed5ce8d..b97520806f 100644 --- a/metricflow/dataflow/builder/source_node_recipe.py +++ b/metricflow/dataflow/builder/source_node_recipe.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from typing import List, Tuple -from metricflow_semantics.specs.instance_spec import LinkableInstanceSpec +from metricflow_semantics.specs.linkable_spec_set import LinkableSpecSet from metricflow.dataflow.builder.node_evaluator import JoinLinkableInstancesRecipe from metricflow.dataflow.dataflow_plan import DataflowPlanNode @@ -15,8 +15,9 @@ class SourceNodeRecipe: """Get a recipe for how to build a dataflow plan node that outputs measures and linkable instances as needed.""" source_node: DataflowPlanNode - required_local_linkable_specs: Tuple[LinkableInstanceSpec, ...] + required_local_linkable_specs: LinkableSpecSet join_linkable_instances_recipes: Tuple[JoinLinkableInstancesRecipe, ...] + all_linkable_specs_required_for_source_nodes: LinkableSpecSet @property def join_targets(self) -> List[JoinDescription]: diff --git a/metricflow/plan_conversion/dataflow_to_sql.py b/metricflow/plan_conversion/dataflow_to_sql.py index a17e4ca2fe..c2016fa1b5 100644 --- a/metricflow/plan_conversion/dataflow_to_sql.py +++ b/metricflow/plan_conversion/dataflow_to_sql.py @@ -1517,7 +1517,7 @@ def visit_join_to_custom_granularity_node(self, node: JoinToCustomGranularityNod parent_column: Optional[SqlSelectColumn] = None assert parent_time_dimension_instance, ( "JoinToCustomGranularityNode's expected time_dimension_spec not found in parent dataset instances. " - f"This indicates internal misconfiguration. Expected: {node.time_dimension_spec.with_base_grain}; " + f"This indicates internal misconfiguration. Expected: {node.time_dimension_spec.with_base_grain()}; " f"Got: {[instance.spec for instance in parent_data_set.instance_set.time_dimension_instances]}" ) for select_column in parent_data_set.checked_sql_select_node.select_columns: diff --git a/tests_metricflow/integration/test_cases/itest_granularity.yaml b/tests_metricflow/integration/test_cases/itest_granularity.yaml index ce10bc95ba..5373b654d9 100644 --- a/tests_metricflow/integration/test_cases/itest_granularity.yaml +++ b/tests_metricflow/integration/test_cases/itest_granularity.yaml @@ -552,3 +552,385 @@ integration_test: LEFT OUTER JOIN {{ source_schema }}.mf_time_spine ts1 ON ts.ds = ts1.ds WHERE {{ render_time_constraint("ts1.martian_day", "2020-01-01") }} GROUP BY ts.ds +--- +integration_test: + name: test_conversion_metric_with_custom_granularity + description: Test querying a conversion metric with a custom grain + model: SIMPLE_MODEL + metrics: ["visit_buy_conversion_rate"] + group_bys: ["metric_time__martian_day"] + check_query: | + SELECT + metric_time__martian_day + , CAST(buys AS {{ double_data_type_name }}) / CAST(NULLIF(visits, 0) AS {{ double_data_type_name }}) AS visit_buy_conversion_rate + FROM ( + SELECT + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_5.visits) AS visits + , MAX(subq_17.buys) AS buys + FROM ( + SELECT + ts.martian_day AS metric_time__martian_day + , SUM(1) AS visits + FROM {{ source_schema }}.fct_visits v + LEFT OUTER JOIN {{ source_schema }}.mf_time_spine ts ON {{ render_date_trunc("V.ds", TimeGranularity.DAY) }} = ts.ds + GROUP BY ts.martian_day + ) subq_5 + FULL OUTER JOIN ( + SELECT + ts2.martian_day AS metric_time__martian_day + , SUM(subq_12.buys) AS buys + FROM ( + SELECT DISTINCT + FIRST_VALUE(subq_8.visits) OVER ( + PARTITION BY subq_11.user, subq_11.ds__day, subq_11.mf_internal_uuid + ORDER BY subq_8.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_8.ds__day) OVER ( + PARTITION BY subq_11.user, subq_11.ds__day, subq_11.mf_internal_uuid + ORDER BY subq_8.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_8.metric_time__day) OVER ( + PARTITION BY subq_11.user, subq_11.ds__day, subq_11.mf_internal_uuid + ORDER BY subq_8.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_8.user) OVER ( + PARTITION BY subq_11.user, subq_11.ds__day, subq_11.mf_internal_uuid + ORDER BY subq_8.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_11.mf_internal_uuid AS mf_internal_uuid + , subq_11.buys AS buys + FROM ( + SELECT + {{ render_date_trunc("ds", TimeGranularity.DAY) }} AS ds__day + , {{ render_date_trunc("ds", TimeGranularity.DAY) }} AS metric_time__day + , user_id AS user + , 1 AS visits + FROM {{ source_schema }}.fct_visits v + ) subq_8 + INNER JOIN ( + SELECT + {{ render_date_trunc("ds", TimeGranularity.DAY) }} AS ds__day + , user_id AS user + , 1 AS buys + , {{ generate_random_uuid() }} AS mf_internal_uuid + FROM {{ source_schema }}.fct_buys b + ) subq_11 + ON subq_8.user = subq_11.user AND subq_8.ds__day <= subq_11.ds__day + ) subq_12 + LEFT OUTER JOIN {{ source_schema }}.mf_time_spine ts2 ON subq_12.metric_time__day = ts2.ds + GROUP BY ts2.martian_day + ) subq_17 + ON subq_5.metric_time__martian_day = subq_17.metric_time__martian_day + GROUP BY COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) + ) subq_18 +--- +integration_test: + name: test_windowed_conversion_metric_with_custom_granularity + description: Test querying a windowed conversion metric with a custom grain + model: SIMPLE_MODEL + metrics: ["visit_buy_conversion_rate_7days"] + group_bys: ["metric_time__martian_day"] + check_query: | + SELECT + metric_time__martian_day + , CAST(buys AS {{ double_data_type_name }}) / CAST(NULLIF(visits, 0) AS {{ double_data_type_name }}) AS visit_buy_conversion_rate_7days + FROM ( + SELECT + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_5.visits) AS visits + , MAX(subq_17.buys) AS buys + FROM ( + SELECT + ts.martian_day AS metric_time__martian_day + , SUM(1) AS visits + FROM {{ source_schema }}.fct_visits v + LEFT OUTER JOIN {{ source_schema }}.mf_time_spine ts ON {{ render_date_trunc("V.ds", TimeGranularity.DAY) }} = ts.ds + GROUP BY ts.martian_day + ) subq_5 + FULL OUTER JOIN ( + SELECT + ts2.martian_day AS metric_time__martian_day + , SUM(subq_12.buys) AS buys + FROM ( + SELECT DISTINCT + FIRST_VALUE(subq_8.visits) OVER ( + PARTITION BY subq_11.user, subq_11.ds__day, subq_11.mf_internal_uuid + ORDER BY subq_8.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_8.ds__day) OVER ( + PARTITION BY + subq_11.user, subq_11.ds__day, subq_11.mf_internal_uuid + ORDER BY subq_8.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_8.metric_time__day) OVER ( + PARTITION BY subq_11.user, subq_11.ds__day, subq_11.mf_internal_uuid + ORDER BY subq_8.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_8.user) OVER ( + PARTITION BY subq_11.user, subq_11.ds__day, subq_11.mf_internal_uuid + ORDER BY subq_8.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_11.mf_internal_uuid AS mf_internal_uuid + , subq_11.buys AS buys + FROM ( + SELECT + {{ render_date_trunc("ds", TimeGranularity.DAY) }} AS ds__day + , {{ render_date_trunc("ds", TimeGranularity.DAY) }} AS metric_time__day + , user_id AS user + , 1 AS visits + FROM {{ source_schema }}.fct_visits v + ) subq_8 + INNER JOIN ( + SELECT + {{ render_date_trunc("ds", TimeGranularity.DAY) }} AS ds__day + , user_id AS user + , 1 AS buys + , {{ generate_random_uuid() }} AS mf_internal_uuid + FROM {{ source_schema }}.fct_buys b + ) subq_11 + ON subq_8.user = subq_11.user AND subq_8.ds__day <= subq_11.ds__day + AND subq_8.ds__day > {{ render_date_sub("subq_11", "ds__day", 7, TimeGranularity.DAY) }} + ) subq_12 + LEFT OUTER JOIN {{ source_schema }}.mf_time_spine ts2 + ON subq_12.metric_time__day = ts2.ds + GROUP BY ts2.martian_day + ) subq_17 + ON subq_5.metric_time__martian_day = subq_17.metric_time__martian_day + GROUP BY COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) + ) subq_18 +--- +integration_test: + name: test_conversion_metric_with_custom_granularity_filter + description: Test querying a conversion metric with a custom grain in the filter (also in group by) + model: SIMPLE_MODEL + metrics: ["visit_buy_conversion_rate"] + group_bys: ["metric_time__martian_day"] + where_filter: | + {{ render_time_constraint(render_time_dimension_template('metric_time', 'martian_day'), start_time="2019-12-20") }} + check_query: | + SELECT + metric_time__martian_day + , CAST(buys AS {{ double_data_type_name }}) / CAST(NULLIF(visits, 0) AS {{ double_data_type_name }}) AS visit_buy_conversion_rate + FROM ( + SELECT + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_6.visits) AS visits + , MAX(subq_19.buys) AS buys + FROM ( + SELECT + metric_time__martian_day + , SUM(visits) AS visits + FROM ( + SELECT + subq_1.visits AS visits + , subq_2.martian_day AS metric_time__martian_day + FROM ( + SELECT + {{ render_date_trunc("ds", TimeGranularity.DAY) }} AS metric_time__day + , 1 AS visits + FROM {{ source_schema }}.fct_visits v + ) subq_1 + LEFT OUTER JOIN + {{ source_schema }}.mf_time_spine subq_2 + ON + subq_1.metric_time__day = subq_2.ds + ) subq_3 + WHERE CAST(metric_time__martian_day AS TIMESTAMP) >= CAST('2019-12-20' AS TIMESTAMP) + GROUP BY + metric_time__martian_day + ) subq_6 + FULL OUTER JOIN ( + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_9.user + , visits + FROM ( + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__day AS metric_time__day + , subq_7.user AS user + , subq_7.visits AS visits + , subq_8.martian_day AS metric_time__martian_day + FROM ( + SELECT + 1 AS visits + , {{ render_date_trunc("ds", TimeGranularity.DAY) }} AS ds__day + , user_id AS user + FROM {{ source_schema }}.fct_visits v + ) subq_7 + LEFT OUTER JOIN + {{ source_schema }}.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE CAST(metric_time__martian_day AS TIMESTAMP) >= CAST('2019-12-20' AS TIMESTAMP) + ) subq_11 + INNER JOIN ( + SELECT + {{ render_date_trunc("ds", TimeGranularity.DAY) }} AS ds__day + , user_id AS user + , 1 AS buys + , {{ generate_random_uuid() }} AS mf_internal_uuid + FROM {{ source_schema }}.fct_buys b + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + (subq_11.ds__day <= subq_14.ds__day) + ) + ) subq_15 + GROUP BY + metric_time__martian_day + ) subq_19 + ON + subq_6.metric_time__martian_day = subq_19.metric_time__martian_day + GROUP BY + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) + ) subq_20 +--- +integration_test: + name: test_conversion_metric_with_custom_granularity_filter_not_in_group_by + description: Test querying a conversion metric with a custom grain in the filter that's not in the group by + model: SIMPLE_MODEL + metrics: ["visit_buy_conversion_rate"] + where_filter: | + {{ render_time_constraint(render_time_dimension_template('metric_time', 'martian_day'), start_time="2019-12-20") }} + check_query: | + SELECT + CAST(MAX(subq_18.buys) AS {{ double_data_type_name }}) / CAST(NULLIF(MAX(subq_6.visits), 0) AS {{ double_data_type_name }}) AS visit_buy_conversion_rate + FROM ( + SELECT + SUM(1) AS visits + FROM {{ source_schema }}.fct_visits v1 + LEFT OUTER JOIN {{ source_schema }}.mf_time_spine ts ON {{ render_date_trunc("v1.ds", TimeGranularity.DAY) }} = ts.ds + WHERE CAST(ts.martian_day AS TIMESTAMP) >= CAST('2019-12-20' AS TIMESTAMP) + ) subq_6 + CROSS JOIN ( + SELECT + SUM(buys) AS buys + FROM ( + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + SELECT + {{ render_date_trunc("v2.ds", TimeGranularity.DAY) }} AS ds__day + , {{ render_date_trunc("v2.ds", TimeGranularity.DAY) }} AS metric_time__day + , v2.user_id AS user + , 1 AS visits + , subq_8.martian_day AS metric_time__martian_day + FROM {{ source_schema }}.fct_visits v2 + LEFT OUTER JOIN {{ source_schema }}.mf_time_spine subq_8 ON {{ render_date_trunc("v2.ds", TimeGranularity.DAY) }} = subq_8.ds + WHERE CAST(subq_8.martian_day AS TIMESTAMP) >= CAST('2019-12-20' AS TIMESTAMP) + ) subq_11 + INNER JOIN ( + SELECT + {{ render_date_trunc("ds", TimeGranularity.DAY) }} AS ds__day + , user_id AS user + , 1 AS buys + , {{ generate_random_uuid() }} AS mf_internal_uuid + FROM {{ source_schema }}.fct_buys b + ) subq_14 + ON subq_11.user = subq_14.user AND subq_11.ds__day <= subq_14.ds__day + ) subq_15 + ) subq_18 diff --git a/tests_metricflow/query_rendering/test_custom_granularity.py b/tests_metricflow/query_rendering/test_custom_granularity.py index beed18d12c..14b5033f50 100644 --- a/tests_metricflow/query_rendering/test_custom_granularity.py +++ b/tests_metricflow/query_rendering/test_custom_granularity.py @@ -455,3 +455,80 @@ def test_offset_metric_with_custom_granularity_filter_not_in_group_by( # noqa: dataflow_plan_builder=dataflow_plan_builder, query_spec=query_spec, ) + + +@pytest.mark.sql_engine_snapshot +def test_conversion_metric_with_custom_granularity( # noqa: D103 + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + sql_client: SqlClient, + query_parser: MetricFlowQueryParser, +) -> None: + query_spec = query_parser.parse_and_validate_query( + metric_names=("visit_buy_conversion_rate_7days",), + group_by_names=("metric_time__martian_day",), + ).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_conversion_metric_with_custom_granularity_filter( # noqa: D103 + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + sql_client: SqlClient, + query_parser: MetricFlowQueryParser, +) -> None: + query_spec = query_parser.parse_and_validate_query( + metric_names=("visit_buy_conversion_rate_7days",), + group_by_names=("metric_time__martian_day",), + where_constraints=[ + 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_conversion_metric_with_custom_granularity_filter_not_in_group_by( # noqa: D103 + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, + dataflow_plan_builder: DataflowPlanBuilder, + dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter, + sql_client: SqlClient, + query_parser: MetricFlowQueryParser, +) -> None: + query_spec = query_parser.parse_and_validate_query( + metric_names=("visit_buy_conversion_rate_7days",), + where_constraints=[ + 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, + ) diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity__plan0.sql new file mode 100644 index 0000000000..e2cc88fbb3 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity__plan0.sql @@ -0,0 +1,422 @@ +-- Compute Metrics via Expressions +SELECT + subq_18.metric_time__martian_day + , CAST(subq_18.buys AS FLOAT64) / CAST(NULLIF(subq_18.visits, 0) AS FLOAT64) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_5.visits) AS visits + , MAX(subq_17.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_4.metric_time__martian_day + , SUM(subq_4.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_3.metric_time__martian_day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS visit__ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS visit__ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS visit__ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS visit__ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS visit__ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + ) subq_4 + GROUP BY + metric_time__martian_day + ) subq_5 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_16.metric_time__martian_day + , SUM(subq_16.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_15.metric_time__martian_day + , subq_15.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_14.metric_time__martian_day + , subq_14.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_13.metric_time__martian_day + , subq_13.ds__day + , subq_13.metric_time__day + , subq_13.user + , subq_13.buys + , subq_13.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_9.visits) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_9.metric_time__martian_day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_9.ds__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_9.metric_time__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_9.user) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_12.mf_internal_uuid AS mf_internal_uuid + , subq_12.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_8.metric_time__martian_day + , subq_8.ds__day + , subq_8.metric_time__day + , subq_8.user + , subq_8.visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_6.ds__day AS ds__day + , subq_6.ds__week AS ds__week + , subq_6.ds__month AS ds__month + , subq_6.ds__quarter AS ds__quarter + , subq_6.ds__year AS ds__year + , subq_6.ds__extract_year AS ds__extract_year + , subq_6.ds__extract_quarter AS ds__extract_quarter + , subq_6.ds__extract_month AS ds__extract_month + , subq_6.ds__extract_day AS ds__extract_day + , subq_6.ds__extract_dow AS ds__extract_dow + , subq_6.ds__extract_doy AS ds__extract_doy + , subq_6.visit__ds__day AS visit__ds__day + , subq_6.visit__ds__week AS visit__ds__week + , subq_6.visit__ds__month AS visit__ds__month + , subq_6.visit__ds__quarter AS visit__ds__quarter + , subq_6.visit__ds__year AS visit__ds__year + , subq_6.visit__ds__extract_year AS visit__ds__extract_year + , subq_6.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_6.visit__ds__extract_month AS visit__ds__extract_month + , subq_6.visit__ds__extract_day AS visit__ds__extract_day + , subq_6.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_6.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_6.ds__day AS metric_time__day + , subq_6.ds__week AS metric_time__week + , subq_6.ds__month AS metric_time__month + , subq_6.ds__quarter AS metric_time__quarter + , subq_6.ds__year AS metric_time__year + , subq_6.ds__extract_year AS metric_time__extract_year + , subq_6.ds__extract_quarter AS metric_time__extract_quarter + , subq_6.ds__extract_month AS metric_time__extract_month + , subq_6.ds__extract_day AS metric_time__extract_day + , subq_6.ds__extract_dow AS metric_time__extract_dow + , subq_6.ds__extract_doy AS metric_time__extract_doy + , subq_6.user AS user + , subq_6.session AS session + , subq_6.visit__user AS visit__user + , subq_6.visit__session AS visit__session + , subq_6.referrer_id AS referrer_id + , subq_6.visit__referrer_id AS visit__referrer_id + , subq_6.visits AS visits + , subq_6.visitors AS visitors + , subq_7.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS visit__ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS visit__ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS visit__ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS visit__ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS visit__ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_6 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_7 + ON + subq_6.ds__day = subq_7.ds + ) subq_8 + ) subq_9 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_11.ds__day + , subq_11.ds__week + , subq_11.ds__month + , subq_11.ds__quarter + , subq_11.ds__year + , subq_11.ds__extract_year + , subq_11.ds__extract_quarter + , subq_11.ds__extract_month + , subq_11.ds__extract_day + , subq_11.ds__extract_dow + , subq_11.ds__extract_doy + , subq_11.buy__ds__day + , subq_11.buy__ds__week + , subq_11.buy__ds__month + , subq_11.buy__ds__quarter + , subq_11.buy__ds__year + , subq_11.buy__ds__extract_year + , subq_11.buy__ds__extract_quarter + , subq_11.buy__ds__extract_month + , subq_11.buy__ds__extract_day + , subq_11.buy__ds__extract_dow + , subq_11.buy__ds__extract_doy + , subq_11.metric_time__day + , subq_11.metric_time__week + , subq_11.metric_time__month + , subq_11.metric_time__quarter + , subq_11.metric_time__year + , subq_11.metric_time__extract_year + , subq_11.metric_time__extract_quarter + , subq_11.metric_time__extract_month + , subq_11.metric_time__extract_day + , subq_11.metric_time__extract_dow + , subq_11.metric_time__extract_doy + , subq_11.user + , subq_11.session_id + , subq_11.buy__user + , subq_11.buy__session_id + , subq_11.buys + , subq_11.buyers + , GENERATE_UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_10.ds__day + , subq_10.ds__week + , subq_10.ds__month + , subq_10.ds__quarter + , subq_10.ds__year + , subq_10.ds__extract_year + , subq_10.ds__extract_quarter + , subq_10.ds__extract_month + , subq_10.ds__extract_day + , subq_10.ds__extract_dow + , subq_10.ds__extract_doy + , subq_10.buy__ds__day + , subq_10.buy__ds__week + , subq_10.buy__ds__month + , subq_10.buy__ds__quarter + , subq_10.buy__ds__year + , subq_10.buy__ds__extract_year + , subq_10.buy__ds__extract_quarter + , subq_10.buy__ds__extract_month + , subq_10.buy__ds__extract_day + , subq_10.buy__ds__extract_dow + , subq_10.buy__ds__extract_doy + , subq_10.ds__day AS metric_time__day + , subq_10.ds__week AS metric_time__week + , subq_10.ds__month AS metric_time__month + , subq_10.ds__quarter AS metric_time__quarter + , subq_10.ds__year AS metric_time__year + , subq_10.ds__extract_year AS metric_time__extract_year + , subq_10.ds__extract_quarter AS metric_time__extract_quarter + , subq_10.ds__extract_month AS metric_time__extract_month + , subq_10.ds__extract_day AS metric_time__extract_day + , subq_10.ds__extract_dow AS metric_time__extract_dow + , subq_10.ds__extract_doy AS metric_time__extract_doy + , subq_10.user + , subq_10.session_id + , subq_10.buy__user + , subq_10.buy__session_id + , subq_10.buys + , subq_10.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATETIME_TRUNC(buys_source_src_28000.ds, day) AS ds__day + , DATETIME_TRUNC(buys_source_src_28000.ds, isoweek) AS ds__week + , DATETIME_TRUNC(buys_source_src_28000.ds, month) AS ds__month + , DATETIME_TRUNC(buys_source_src_28000.ds, quarter) AS ds__quarter + , DATETIME_TRUNC(buys_source_src_28000.ds, year) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , IF(EXTRACT(dayofweek FROM buys_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM buys_source_src_28000.ds) - 1) AS ds__extract_dow + , EXTRACT(dayofyear FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATETIME_TRUNC(buys_source_src_28000.ds, day) AS buy__ds__day + , DATETIME_TRUNC(buys_source_src_28000.ds, isoweek) AS buy__ds__week + , DATETIME_TRUNC(buys_source_src_28000.ds, month) AS buy__ds__month + , DATETIME_TRUNC(buys_source_src_28000.ds, quarter) AS buy__ds__quarter + , DATETIME_TRUNC(buys_source_src_28000.ds, year) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , IF(EXTRACT(dayofweek FROM buys_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM buys_source_src_28000.ds) - 1) AS buy__ds__extract_dow + , EXTRACT(dayofyear FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_10 + ) subq_11 + ) subq_12 + ON + ( + subq_9.user = subq_12.user + ) AND ( + ( + subq_9.ds__day <= subq_12.ds__day + ) AND ( + subq_9.ds__day > DATE_SUB(CAST(subq_12.ds__day AS DATETIME), INTERVAL 7 day) + ) + ) + ) subq_13 + ) subq_14 + ) subq_15 + ) subq_16 + GROUP BY + metric_time__martian_day + ) subq_17 + ON + subq_5.metric_time__martian_day = subq_17.metric_time__martian_day + GROUP BY + metric_time__martian_day +) subq_18 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity__plan0_optimized.sql new file mode 100644 index 0000000000..08e49da840 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity__plan0_optimized.sql @@ -0,0 +1,139 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS FLOAT64) / CAST(NULLIF(visits, 0) AS FLOAT64) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_24.visits) AS visits + , MAX(subq_36.buys) AS buys + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + subq_21.martian_day AS metric_time__martian_day + , SUM(subq_20.visits) AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATETIME_TRUNC(ds, day) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_20 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_21 + ON + subq_20.metric_time__day = subq_21.ds + GROUP BY + metric_time__martian_day + ) subq_24 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_28.visits) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_28.metric_time__martian_day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_28.ds__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_28.metric_time__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_28.user) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_31.mf_internal_uuid AS mf_internal_uuid + , subq_31.buys AS buys + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_26.martian_day AS metric_time__martian_day + , subq_25.ds__day AS ds__day + , subq_25.ds__day AS metric_time__day + , subq_25.user AS user + , subq_25.visits AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATETIME_TRUNC(ds, day) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_25 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_26 + ON + subq_25.ds__day = subq_26.ds + ) subq_28 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATETIME_TRUNC(ds, day) AS ds__day + , user_id AS user + , 1 AS buys + , GENERATE_UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_31 + ON + ( + subq_28.user = subq_31.user + ) AND ( + ( + subq_28.ds__day <= subq_31.ds__day + ) AND ( + subq_28.ds__day > DATE_SUB(CAST(subq_31.ds__day AS DATETIME), INTERVAL 7 day) + ) + ) + ) subq_32 + GROUP BY + metric_time__martian_day + ) subq_36 + ON + subq_24.metric_time__martian_day = subq_36.metric_time__martian_day + GROUP BY + metric_time__martian_day +) subq_37 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter__plan0.sql new file mode 100644 index 0000000000..056e70d976 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter__plan0.sql @@ -0,0 +1,477 @@ +-- Compute Metrics via Expressions +SELECT + subq_20.metric_time__martian_day + , CAST(subq_20.buys AS FLOAT64) / CAST(NULLIF(subq_20.visits, 0) AS FLOAT64) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_6.visits) AS visits + , MAX(subq_19.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__martian_day + , SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_4.metric_time__martian_day + , subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS visit__ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS visit__ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS visit__ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS visit__ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS visit__ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + GROUP BY + metric_time__martian_day + ) subq_6 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_18.metric_time__martian_day + , SUM(subq_18.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_17.metric_time__martian_day + , subq_17.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_16.metric_time__martian_day + , subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS visit__ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS visit__ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS visit__ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS visit__ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS visit__ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , GENERATE_UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATETIME_TRUNC(buys_source_src_28000.ds, day) AS ds__day + , DATETIME_TRUNC(buys_source_src_28000.ds, isoweek) AS ds__week + , DATETIME_TRUNC(buys_source_src_28000.ds, month) AS ds__month + , DATETIME_TRUNC(buys_source_src_28000.ds, quarter) AS ds__quarter + , DATETIME_TRUNC(buys_source_src_28000.ds, year) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , IF(EXTRACT(dayofweek FROM buys_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM buys_source_src_28000.ds) - 1) AS ds__extract_dow + , EXTRACT(dayofyear FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATETIME_TRUNC(buys_source_src_28000.ds, day) AS buy__ds__day + , DATETIME_TRUNC(buys_source_src_28000.ds, isoweek) AS buy__ds__week + , DATETIME_TRUNC(buys_source_src_28000.ds, month) AS buy__ds__month + , DATETIME_TRUNC(buys_source_src_28000.ds, quarter) AS buy__ds__quarter + , DATETIME_TRUNC(buys_source_src_28000.ds, year) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , IF(EXTRACT(dayofweek FROM buys_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM buys_source_src_28000.ds) - 1) AS buy__ds__extract_dow + , EXTRACT(dayofyear FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > DATE_SUB(CAST(subq_14.ds__day AS DATETIME), INTERVAL 7 day) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 + GROUP BY + metric_time__martian_day + ) subq_19 + ON + subq_6.metric_time__martian_day = subq_19.metric_time__martian_day + GROUP BY + metric_time__martian_day +) subq_20 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql new file mode 100644 index 0000000000..9eb7c0ac1b --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql @@ -0,0 +1,156 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS FLOAT64) / CAST(NULLIF(visits, 0) AS FLOAT64) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_27.visits) AS visits + , MAX(subq_40.buys) AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_22.visits AS visits + , subq_23.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATETIME_TRUNC(ds, day) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_22 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_23 + ON + subq_22.metric_time__day = subq_23.ds + ) subq_24 + WHERE metric_time__martian_day = '2020-01-01' + GROUP BY + metric_time__martian_day + ) subq_27 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_32.visits) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_32.metric_time__martian_day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_32.ds__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_32.metric_time__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_32.user) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_35.mf_internal_uuid AS mf_internal_uuid + , subq_35.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_30.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_28.ds__day AS ds__day + , subq_28.ds__day AS metric_time__day + , subq_28.user AS user + , subq_28.visits AS visits + , subq_29.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATETIME_TRUNC(ds, day) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_28 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_29 + ON + subq_28.ds__day = subq_29.ds + ) subq_30 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_32 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATETIME_TRUNC(ds, day) AS ds__day + , user_id AS user + , 1 AS buys + , GENERATE_UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_35 + ON + ( + subq_32.user = subq_35.user + ) AND ( + ( + subq_32.ds__day <= subq_35.ds__day + ) AND ( + subq_32.ds__day > DATE_SUB(CAST(subq_35.ds__day AS DATETIME), INTERVAL 7 day) + ) + ) + ) subq_36 + GROUP BY + metric_time__martian_day + ) subq_40 + ON + subq_27.metric_time__martian_day = subq_40.metric_time__martian_day + GROUP BY + metric_time__martian_day +) subq_41 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql new file mode 100644 index 0000000000..403f64d823 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql @@ -0,0 +1,457 @@ +-- Compute Metrics via Expressions +SELECT + CAST(subq_19.buys AS FLOAT64) / CAST(NULLIF(subq_19.visits, 0) AS FLOAT64) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + MAX(subq_6.visits) AS visits + , MAX(subq_18.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits',] + SELECT + subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS visit__ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS visit__ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS visit__ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS visit__ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS visit__ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + CROSS JOIN ( + -- Aggregate Measures + SELECT + SUM(subq_17.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys',] + SELECT + subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATETIME_TRUNC(visits_source_src_28000.ds, day) AS visit__ds__day + , DATETIME_TRUNC(visits_source_src_28000.ds, isoweek) AS visit__ds__week + , DATETIME_TRUNC(visits_source_src_28000.ds, month) AS visit__ds__month + , DATETIME_TRUNC(visits_source_src_28000.ds, quarter) AS visit__ds__quarter + , DATETIME_TRUNC(visits_source_src_28000.ds, year) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , IF(EXTRACT(dayofweek FROM visits_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM visits_source_src_28000.ds) - 1) AS visit__ds__extract_dow + , EXTRACT(dayofyear FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , GENERATE_UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATETIME_TRUNC(buys_source_src_28000.ds, day) AS ds__day + , DATETIME_TRUNC(buys_source_src_28000.ds, isoweek) AS ds__week + , DATETIME_TRUNC(buys_source_src_28000.ds, month) AS ds__month + , DATETIME_TRUNC(buys_source_src_28000.ds, quarter) AS ds__quarter + , DATETIME_TRUNC(buys_source_src_28000.ds, year) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , IF(EXTRACT(dayofweek FROM buys_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM buys_source_src_28000.ds) - 1) AS ds__extract_dow + , EXTRACT(dayofyear FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATETIME_TRUNC(buys_source_src_28000.ds, day) AS buy__ds__day + , DATETIME_TRUNC(buys_source_src_28000.ds, isoweek) AS buy__ds__week + , DATETIME_TRUNC(buys_source_src_28000.ds, month) AS buy__ds__month + , DATETIME_TRUNC(buys_source_src_28000.ds, quarter) AS buy__ds__quarter + , DATETIME_TRUNC(buys_source_src_28000.ds, year) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , IF(EXTRACT(dayofweek FROM buys_source_src_28000.ds) = 1, 7, EXTRACT(dayofweek FROM buys_source_src_28000.ds) - 1) AS buy__ds__extract_dow + , EXTRACT(dayofyear FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > DATE_SUB(CAST(subq_14.ds__day AS DATETIME), INTERVAL 7 day) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 +) subq_19 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql new file mode 100644 index 0000000000..b1e0e18adb --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/BigQuery/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql @@ -0,0 +1,138 @@ +-- Combine Aggregated Outputs +-- Compute Metrics via Expressions +SELECT + CAST(MAX(subq_38.buys) AS FLOAT64) / CAST(NULLIF(MAX(subq_26.visits), 0) AS FLOAT64) AS visit_buy_conversion_rate_7days +FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits',] + -- Aggregate Measures + SELECT + SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_21.visits AS visits + , subq_22.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATETIME_TRUNC(ds, day) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_21 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_22 + ON + subq_21.metric_time__day = subq_22.ds + ) subq_23 + WHERE metric_time__martian_day = '2020-01-01' +) subq_26 +CROSS JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys',] + -- Aggregate Measures + SELECT + SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_31.visits) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_31.metric_time__martian_day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_31.ds__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_31.metric_time__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_31.user) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_34.mf_internal_uuid AS mf_internal_uuid + , subq_34.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_29.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_27.ds__day AS ds__day + , subq_27.ds__day AS metric_time__day + , subq_27.user AS user + , subq_27.visits AS visits + , subq_28.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATETIME_TRUNC(ds, day) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_27 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_28 + ON + subq_27.ds__day = subq_28.ds + ) subq_29 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_31 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATETIME_TRUNC(ds, day) AS ds__day + , user_id AS user + , 1 AS buys + , GENERATE_UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_34 + ON + ( + subq_31.user = subq_34.user + ) AND ( + ( + subq_31.ds__day <= subq_34.ds__day + ) AND ( + subq_31.ds__day > DATE_SUB(CAST(subq_34.ds__day AS DATETIME), INTERVAL 7 day) + ) + ) + ) subq_35 +) subq_38 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity__plan0.sql new file mode 100644 index 0000000000..16abfd3ffb --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity__plan0.sql @@ -0,0 +1,422 @@ +-- Compute Metrics via Expressions +SELECT + subq_18.metric_time__martian_day + , CAST(subq_18.buys AS DOUBLE) / CAST(NULLIF(subq_18.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_5.visits) AS visits + , MAX(subq_17.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_4.metric_time__martian_day + , SUM(subq_4.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_3.metric_time__martian_day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + ) subq_4 + GROUP BY + subq_4.metric_time__martian_day + ) subq_5 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_16.metric_time__martian_day + , SUM(subq_16.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_15.metric_time__martian_day + , subq_15.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_14.metric_time__martian_day + , subq_14.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_13.metric_time__martian_day + , subq_13.ds__day + , subq_13.metric_time__day + , subq_13.user + , subq_13.buys + , subq_13.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_9.visits) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_9.metric_time__martian_day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_9.ds__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_9.metric_time__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_9.user) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_12.mf_internal_uuid AS mf_internal_uuid + , subq_12.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_8.metric_time__martian_day + , subq_8.ds__day + , subq_8.metric_time__day + , subq_8.user + , subq_8.visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_6.ds__day AS ds__day + , subq_6.ds__week AS ds__week + , subq_6.ds__month AS ds__month + , subq_6.ds__quarter AS ds__quarter + , subq_6.ds__year AS ds__year + , subq_6.ds__extract_year AS ds__extract_year + , subq_6.ds__extract_quarter AS ds__extract_quarter + , subq_6.ds__extract_month AS ds__extract_month + , subq_6.ds__extract_day AS ds__extract_day + , subq_6.ds__extract_dow AS ds__extract_dow + , subq_6.ds__extract_doy AS ds__extract_doy + , subq_6.visit__ds__day AS visit__ds__day + , subq_6.visit__ds__week AS visit__ds__week + , subq_6.visit__ds__month AS visit__ds__month + , subq_6.visit__ds__quarter AS visit__ds__quarter + , subq_6.visit__ds__year AS visit__ds__year + , subq_6.visit__ds__extract_year AS visit__ds__extract_year + , subq_6.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_6.visit__ds__extract_month AS visit__ds__extract_month + , subq_6.visit__ds__extract_day AS visit__ds__extract_day + , subq_6.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_6.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_6.ds__day AS metric_time__day + , subq_6.ds__week AS metric_time__week + , subq_6.ds__month AS metric_time__month + , subq_6.ds__quarter AS metric_time__quarter + , subq_6.ds__year AS metric_time__year + , subq_6.ds__extract_year AS metric_time__extract_year + , subq_6.ds__extract_quarter AS metric_time__extract_quarter + , subq_6.ds__extract_month AS metric_time__extract_month + , subq_6.ds__extract_day AS metric_time__extract_day + , subq_6.ds__extract_dow AS metric_time__extract_dow + , subq_6.ds__extract_doy AS metric_time__extract_doy + , subq_6.user AS user + , subq_6.session AS session + , subq_6.visit__user AS visit__user + , subq_6.visit__session AS visit__session + , subq_6.referrer_id AS referrer_id + , subq_6.visit__referrer_id AS visit__referrer_id + , subq_6.visits AS visits + , subq_6.visitors AS visitors + , subq_7.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_6 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_7 + ON + subq_6.ds__day = subq_7.ds + ) subq_8 + ) subq_9 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_11.ds__day + , subq_11.ds__week + , subq_11.ds__month + , subq_11.ds__quarter + , subq_11.ds__year + , subq_11.ds__extract_year + , subq_11.ds__extract_quarter + , subq_11.ds__extract_month + , subq_11.ds__extract_day + , subq_11.ds__extract_dow + , subq_11.ds__extract_doy + , subq_11.buy__ds__day + , subq_11.buy__ds__week + , subq_11.buy__ds__month + , subq_11.buy__ds__quarter + , subq_11.buy__ds__year + , subq_11.buy__ds__extract_year + , subq_11.buy__ds__extract_quarter + , subq_11.buy__ds__extract_month + , subq_11.buy__ds__extract_day + , subq_11.buy__ds__extract_dow + , subq_11.buy__ds__extract_doy + , subq_11.metric_time__day + , subq_11.metric_time__week + , subq_11.metric_time__month + , subq_11.metric_time__quarter + , subq_11.metric_time__year + , subq_11.metric_time__extract_year + , subq_11.metric_time__extract_quarter + , subq_11.metric_time__extract_month + , subq_11.metric_time__extract_day + , subq_11.metric_time__extract_dow + , subq_11.metric_time__extract_doy + , subq_11.user + , subq_11.session_id + , subq_11.buy__user + , subq_11.buy__session_id + , subq_11.buys + , subq_11.buyers + , UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_10.ds__day + , subq_10.ds__week + , subq_10.ds__month + , subq_10.ds__quarter + , subq_10.ds__year + , subq_10.ds__extract_year + , subq_10.ds__extract_quarter + , subq_10.ds__extract_month + , subq_10.ds__extract_day + , subq_10.ds__extract_dow + , subq_10.ds__extract_doy + , subq_10.buy__ds__day + , subq_10.buy__ds__week + , subq_10.buy__ds__month + , subq_10.buy__ds__quarter + , subq_10.buy__ds__year + , subq_10.buy__ds__extract_year + , subq_10.buy__ds__extract_quarter + , subq_10.buy__ds__extract_month + , subq_10.buy__ds__extract_day + , subq_10.buy__ds__extract_dow + , subq_10.buy__ds__extract_doy + , subq_10.ds__day AS metric_time__day + , subq_10.ds__week AS metric_time__week + , subq_10.ds__month AS metric_time__month + , subq_10.ds__quarter AS metric_time__quarter + , subq_10.ds__year AS metric_time__year + , subq_10.ds__extract_year AS metric_time__extract_year + , subq_10.ds__extract_quarter AS metric_time__extract_quarter + , subq_10.ds__extract_month AS metric_time__extract_month + , subq_10.ds__extract_day AS metric_time__extract_day + , subq_10.ds__extract_dow AS metric_time__extract_dow + , subq_10.ds__extract_doy AS metric_time__extract_doy + , subq_10.user + , subq_10.session_id + , subq_10.buy__user + , subq_10.buy__session_id + , subq_10.buys + , subq_10.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_10 + ) subq_11 + ) subq_12 + ON + ( + subq_9.user = subq_12.user + ) AND ( + ( + subq_9.ds__day <= subq_12.ds__day + ) AND ( + subq_9.ds__day > DATEADD(day, -7, subq_12.ds__day) + ) + ) + ) subq_13 + ) subq_14 + ) subq_15 + ) subq_16 + GROUP BY + subq_16.metric_time__martian_day + ) subq_17 + ON + subq_5.metric_time__martian_day = subq_17.metric_time__martian_day + GROUP BY + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) +) subq_18 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity__plan0_optimized.sql new file mode 100644 index 0000000000..5d824995d9 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity__plan0_optimized.sql @@ -0,0 +1,139 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE) / CAST(NULLIF(visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_24.visits) AS visits + , MAX(subq_36.buys) AS buys + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + subq_21.martian_day AS metric_time__martian_day + , SUM(subq_20.visits) AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_20 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_21 + ON + subq_20.metric_time__day = subq_21.ds + GROUP BY + subq_21.martian_day + ) subq_24 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_28.visits) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_28.metric_time__martian_day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_28.ds__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_28.metric_time__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_28.user) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_31.mf_internal_uuid AS mf_internal_uuid + , subq_31.buys AS buys + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_26.martian_day AS metric_time__martian_day + , subq_25.ds__day AS ds__day + , subq_25.ds__day AS metric_time__day + , subq_25.user AS user + , subq_25.visits AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_25 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_26 + ON + subq_25.ds__day = subq_26.ds + ) subq_28 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_31 + ON + ( + subq_28.user = subq_31.user + ) AND ( + ( + subq_28.ds__day <= subq_31.ds__day + ) AND ( + subq_28.ds__day > DATEADD(day, -7, subq_31.ds__day) + ) + ) + ) subq_32 + GROUP BY + metric_time__martian_day + ) subq_36 + ON + subq_24.metric_time__martian_day = subq_36.metric_time__martian_day + GROUP BY + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) +) subq_37 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter__plan0.sql new file mode 100644 index 0000000000..bceeecbf98 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter__plan0.sql @@ -0,0 +1,477 @@ +-- Compute Metrics via Expressions +SELECT + subq_20.metric_time__martian_day + , CAST(subq_20.buys AS DOUBLE) / CAST(NULLIF(subq_20.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_6.visits) AS visits + , MAX(subq_19.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__martian_day + , SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_4.metric_time__martian_day + , subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + GROUP BY + subq_5.metric_time__martian_day + ) subq_6 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_18.metric_time__martian_day + , SUM(subq_18.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_17.metric_time__martian_day + , subq_17.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_16.metric_time__martian_day + , subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > DATEADD(day, -7, subq_14.ds__day) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 + GROUP BY + subq_18.metric_time__martian_day + ) subq_19 + ON + subq_6.metric_time__martian_day = subq_19.metric_time__martian_day + GROUP BY + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) +) subq_20 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql new file mode 100644 index 0000000000..ddd4ba3c2d --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql @@ -0,0 +1,156 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE) / CAST(NULLIF(visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_27.visits) AS visits + , MAX(subq_40.buys) AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_22.visits AS visits + , subq_23.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_22 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_23 + ON + subq_22.metric_time__day = subq_23.ds + ) subq_24 + WHERE metric_time__martian_day = '2020-01-01' + GROUP BY + metric_time__martian_day + ) subq_27 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_32.visits) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_32.metric_time__martian_day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_32.ds__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_32.metric_time__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_32.user) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_35.mf_internal_uuid AS mf_internal_uuid + , subq_35.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_30.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_28.ds__day AS ds__day + , subq_28.ds__day AS metric_time__day + , subq_28.user AS user + , subq_28.visits AS visits + , subq_29.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_28 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_29 + ON + subq_28.ds__day = subq_29.ds + ) subq_30 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_32 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_35 + ON + ( + subq_32.user = subq_35.user + ) AND ( + ( + subq_32.ds__day <= subq_35.ds__day + ) AND ( + subq_32.ds__day > DATEADD(day, -7, subq_35.ds__day) + ) + ) + ) subq_36 + GROUP BY + metric_time__martian_day + ) subq_40 + ON + subq_27.metric_time__martian_day = subq_40.metric_time__martian_day + GROUP BY + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) +) subq_41 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql new file mode 100644 index 0000000000..765c26307f --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql @@ -0,0 +1,457 @@ +-- Compute Metrics via Expressions +SELECT + CAST(subq_19.buys AS DOUBLE) / CAST(NULLIF(subq_19.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + MAX(subq_6.visits) AS visits + , MAX(subq_18.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits',] + SELECT + subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + CROSS JOIN ( + -- Aggregate Measures + SELECT + SUM(subq_17.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys',] + SELECT + subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(DAYOFWEEK_ISO FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > DATEADD(day, -7, subq_14.ds__day) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 +) subq_19 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql new file mode 100644 index 0000000000..f31db54869 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Databricks/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql @@ -0,0 +1,138 @@ +-- Combine Aggregated Outputs +-- Compute Metrics via Expressions +SELECT + CAST(MAX(subq_38.buys) AS DOUBLE) / CAST(NULLIF(MAX(subq_26.visits), 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits',] + -- Aggregate Measures + SELECT + SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_21.visits AS visits + , subq_22.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_21 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_22 + ON + subq_21.metric_time__day = subq_22.ds + ) subq_23 + WHERE metric_time__martian_day = '2020-01-01' +) subq_26 +CROSS JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys',] + -- Aggregate Measures + SELECT + SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_31.visits) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_31.metric_time__martian_day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_31.ds__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_31.metric_time__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_31.user) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_34.mf_internal_uuid AS mf_internal_uuid + , subq_34.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_29.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_27.ds__day AS ds__day + , subq_27.ds__day AS metric_time__day + , subq_27.user AS user + , subq_27.visits AS visits + , subq_28.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_27 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_28 + ON + subq_27.ds__day = subq_28.ds + ) subq_29 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_31 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_34 + ON + ( + subq_31.user = subq_34.user + ) AND ( + ( + subq_31.ds__day <= subq_34.ds__day + ) AND ( + subq_31.ds__day > DATEADD(day, -7, subq_34.ds__day) + ) + ) + ) subq_35 +) subq_38 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity__plan0.sql new file mode 100644 index 0000000000..fa6679520b --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity__plan0.sql @@ -0,0 +1,422 @@ +-- Compute Metrics via Expressions +SELECT + subq_18.metric_time__martian_day + , CAST(subq_18.buys AS DOUBLE) / CAST(NULLIF(subq_18.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_5.visits) AS visits + , MAX(subq_17.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_4.metric_time__martian_day + , SUM(subq_4.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_3.metric_time__martian_day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + ) subq_4 + GROUP BY + subq_4.metric_time__martian_day + ) subq_5 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_16.metric_time__martian_day + , SUM(subq_16.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_15.metric_time__martian_day + , subq_15.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_14.metric_time__martian_day + , subq_14.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_13.metric_time__martian_day + , subq_13.ds__day + , subq_13.metric_time__day + , subq_13.user + , subq_13.buys + , subq_13.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_9.visits) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_9.metric_time__martian_day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_9.ds__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_9.metric_time__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_9.user) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_12.mf_internal_uuid AS mf_internal_uuid + , subq_12.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_8.metric_time__martian_day + , subq_8.ds__day + , subq_8.metric_time__day + , subq_8.user + , subq_8.visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_6.ds__day AS ds__day + , subq_6.ds__week AS ds__week + , subq_6.ds__month AS ds__month + , subq_6.ds__quarter AS ds__quarter + , subq_6.ds__year AS ds__year + , subq_6.ds__extract_year AS ds__extract_year + , subq_6.ds__extract_quarter AS ds__extract_quarter + , subq_6.ds__extract_month AS ds__extract_month + , subq_6.ds__extract_day AS ds__extract_day + , subq_6.ds__extract_dow AS ds__extract_dow + , subq_6.ds__extract_doy AS ds__extract_doy + , subq_6.visit__ds__day AS visit__ds__day + , subq_6.visit__ds__week AS visit__ds__week + , subq_6.visit__ds__month AS visit__ds__month + , subq_6.visit__ds__quarter AS visit__ds__quarter + , subq_6.visit__ds__year AS visit__ds__year + , subq_6.visit__ds__extract_year AS visit__ds__extract_year + , subq_6.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_6.visit__ds__extract_month AS visit__ds__extract_month + , subq_6.visit__ds__extract_day AS visit__ds__extract_day + , subq_6.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_6.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_6.ds__day AS metric_time__day + , subq_6.ds__week AS metric_time__week + , subq_6.ds__month AS metric_time__month + , subq_6.ds__quarter AS metric_time__quarter + , subq_6.ds__year AS metric_time__year + , subq_6.ds__extract_year AS metric_time__extract_year + , subq_6.ds__extract_quarter AS metric_time__extract_quarter + , subq_6.ds__extract_month AS metric_time__extract_month + , subq_6.ds__extract_day AS metric_time__extract_day + , subq_6.ds__extract_dow AS metric_time__extract_dow + , subq_6.ds__extract_doy AS metric_time__extract_doy + , subq_6.user AS user + , subq_6.session AS session + , subq_6.visit__user AS visit__user + , subq_6.visit__session AS visit__session + , subq_6.referrer_id AS referrer_id + , subq_6.visit__referrer_id AS visit__referrer_id + , subq_6.visits AS visits + , subq_6.visitors AS visitors + , subq_7.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_6 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_7 + ON + subq_6.ds__day = subq_7.ds + ) subq_8 + ) subq_9 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_11.ds__day + , subq_11.ds__week + , subq_11.ds__month + , subq_11.ds__quarter + , subq_11.ds__year + , subq_11.ds__extract_year + , subq_11.ds__extract_quarter + , subq_11.ds__extract_month + , subq_11.ds__extract_day + , subq_11.ds__extract_dow + , subq_11.ds__extract_doy + , subq_11.buy__ds__day + , subq_11.buy__ds__week + , subq_11.buy__ds__month + , subq_11.buy__ds__quarter + , subq_11.buy__ds__year + , subq_11.buy__ds__extract_year + , subq_11.buy__ds__extract_quarter + , subq_11.buy__ds__extract_month + , subq_11.buy__ds__extract_day + , subq_11.buy__ds__extract_dow + , subq_11.buy__ds__extract_doy + , subq_11.metric_time__day + , subq_11.metric_time__week + , subq_11.metric_time__month + , subq_11.metric_time__quarter + , subq_11.metric_time__year + , subq_11.metric_time__extract_year + , subq_11.metric_time__extract_quarter + , subq_11.metric_time__extract_month + , subq_11.metric_time__extract_day + , subq_11.metric_time__extract_dow + , subq_11.metric_time__extract_doy + , subq_11.user + , subq_11.session_id + , subq_11.buy__user + , subq_11.buy__session_id + , subq_11.buys + , subq_11.buyers + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_10.ds__day + , subq_10.ds__week + , subq_10.ds__month + , subq_10.ds__quarter + , subq_10.ds__year + , subq_10.ds__extract_year + , subq_10.ds__extract_quarter + , subq_10.ds__extract_month + , subq_10.ds__extract_day + , subq_10.ds__extract_dow + , subq_10.ds__extract_doy + , subq_10.buy__ds__day + , subq_10.buy__ds__week + , subq_10.buy__ds__month + , subq_10.buy__ds__quarter + , subq_10.buy__ds__year + , subq_10.buy__ds__extract_year + , subq_10.buy__ds__extract_quarter + , subq_10.buy__ds__extract_month + , subq_10.buy__ds__extract_day + , subq_10.buy__ds__extract_dow + , subq_10.buy__ds__extract_doy + , subq_10.ds__day AS metric_time__day + , subq_10.ds__week AS metric_time__week + , subq_10.ds__month AS metric_time__month + , subq_10.ds__quarter AS metric_time__quarter + , subq_10.ds__year AS metric_time__year + , subq_10.ds__extract_year AS metric_time__extract_year + , subq_10.ds__extract_quarter AS metric_time__extract_quarter + , subq_10.ds__extract_month AS metric_time__extract_month + , subq_10.ds__extract_day AS metric_time__extract_day + , subq_10.ds__extract_dow AS metric_time__extract_dow + , subq_10.ds__extract_doy AS metric_time__extract_doy + , subq_10.user + , subq_10.session_id + , subq_10.buy__user + , subq_10.buy__session_id + , subq_10.buys + , subq_10.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_10 + ) subq_11 + ) subq_12 + ON + ( + subq_9.user = subq_12.user + ) AND ( + ( + subq_9.ds__day <= subq_12.ds__day + ) AND ( + subq_9.ds__day > subq_12.ds__day - INTERVAL 7 day + ) + ) + ) subq_13 + ) subq_14 + ) subq_15 + ) subq_16 + GROUP BY + subq_16.metric_time__martian_day + ) subq_17 + ON + subq_5.metric_time__martian_day = subq_17.metric_time__martian_day + GROUP BY + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) +) subq_18 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity__plan0_optimized.sql new file mode 100644 index 0000000000..8ad1665267 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity__plan0_optimized.sql @@ -0,0 +1,139 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE) / CAST(NULLIF(visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_24.visits) AS visits + , MAX(subq_36.buys) AS buys + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + subq_21.martian_day AS metric_time__martian_day + , SUM(subq_20.visits) AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_20 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_21 + ON + subq_20.metric_time__day = subq_21.ds + GROUP BY + subq_21.martian_day + ) subq_24 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_28.visits) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_28.metric_time__martian_day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_28.ds__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_28.metric_time__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_28.user) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_31.mf_internal_uuid AS mf_internal_uuid + , subq_31.buys AS buys + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_26.martian_day AS metric_time__martian_day + , subq_25.ds__day AS ds__day + , subq_25.ds__day AS metric_time__day + , subq_25.user AS user + , subq_25.visits AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_25 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_26 + ON + subq_25.ds__day = subq_26.ds + ) subq_28 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_31 + ON + ( + subq_28.user = subq_31.user + ) AND ( + ( + subq_28.ds__day <= subq_31.ds__day + ) AND ( + subq_28.ds__day > subq_31.ds__day - INTERVAL 7 day + ) + ) + ) subq_32 + GROUP BY + metric_time__martian_day + ) subq_36 + ON + subq_24.metric_time__martian_day = subq_36.metric_time__martian_day + GROUP BY + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) +) subq_37 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter__plan0.sql new file mode 100644 index 0000000000..e2d181879f --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter__plan0.sql @@ -0,0 +1,477 @@ +-- Compute Metrics via Expressions +SELECT + subq_20.metric_time__martian_day + , CAST(subq_20.buys AS DOUBLE) / CAST(NULLIF(subq_20.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_6.visits) AS visits + , MAX(subq_19.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__martian_day + , SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_4.metric_time__martian_day + , subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + GROUP BY + subq_5.metric_time__martian_day + ) subq_6 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_18.metric_time__martian_day + , SUM(subq_18.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_17.metric_time__martian_day + , subq_17.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_16.metric_time__martian_day + , subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > subq_14.ds__day - INTERVAL 7 day + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 + GROUP BY + subq_18.metric_time__martian_day + ) subq_19 + ON + subq_6.metric_time__martian_day = subq_19.metric_time__martian_day + GROUP BY + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) +) subq_20 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql new file mode 100644 index 0000000000..d2eefd11b4 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql @@ -0,0 +1,156 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE) / CAST(NULLIF(visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_27.visits) AS visits + , MAX(subq_40.buys) AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_22.visits AS visits + , subq_23.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_22 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_23 + ON + subq_22.metric_time__day = subq_23.ds + ) subq_24 + WHERE metric_time__martian_day = '2020-01-01' + GROUP BY + metric_time__martian_day + ) subq_27 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_32.visits) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_32.metric_time__martian_day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_32.ds__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_32.metric_time__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_32.user) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_35.mf_internal_uuid AS mf_internal_uuid + , subq_35.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_30.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_28.ds__day AS ds__day + , subq_28.ds__day AS metric_time__day + , subq_28.user AS user + , subq_28.visits AS visits + , subq_29.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_28 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_29 + ON + subq_28.ds__day = subq_29.ds + ) subq_30 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_32 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_35 + ON + ( + subq_32.user = subq_35.user + ) AND ( + ( + subq_32.ds__day <= subq_35.ds__day + ) AND ( + subq_32.ds__day > subq_35.ds__day - INTERVAL 7 day + ) + ) + ) subq_36 + GROUP BY + metric_time__martian_day + ) subq_40 + ON + subq_27.metric_time__martian_day = subq_40.metric_time__martian_day + GROUP BY + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) +) subq_41 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql new file mode 100644 index 0000000000..864f6857d4 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql @@ -0,0 +1,457 @@ +-- Compute Metrics via Expressions +SELECT + CAST(subq_19.buys AS DOUBLE) / CAST(NULLIF(subq_19.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + MAX(subq_6.visits) AS visits + , MAX(subq_18.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits',] + SELECT + subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + CROSS JOIN ( + -- Aggregate Measures + SELECT + SUM(subq_17.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys',] + SELECT + subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > subq_14.ds__day - INTERVAL 7 day + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 +) subq_19 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql new file mode 100644 index 0000000000..aace264fae --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/DuckDB/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql @@ -0,0 +1,138 @@ +-- Combine Aggregated Outputs +-- Compute Metrics via Expressions +SELECT + CAST(MAX(subq_38.buys) AS DOUBLE) / CAST(NULLIF(MAX(subq_26.visits), 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits',] + -- Aggregate Measures + SELECT + SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_21.visits AS visits + , subq_22.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_21 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_22 + ON + subq_21.metric_time__day = subq_22.ds + ) subq_23 + WHERE metric_time__martian_day = '2020-01-01' +) subq_26 +CROSS JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys',] + -- Aggregate Measures + SELECT + SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_31.visits) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_31.metric_time__martian_day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_31.ds__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_31.metric_time__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_31.user) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_34.mf_internal_uuid AS mf_internal_uuid + , subq_34.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_29.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_27.ds__day AS ds__day + , subq_27.ds__day AS metric_time__day + , subq_27.user AS user + , subq_27.visits AS visits + , subq_28.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_27 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_28 + ON + subq_27.ds__day = subq_28.ds + ) subq_29 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_31 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_34 + ON + ( + subq_31.user = subq_34.user + ) AND ( + ( + subq_31.ds__day <= subq_34.ds__day + ) AND ( + subq_31.ds__day > subq_34.ds__day - INTERVAL 7 day + ) + ) + ) subq_35 +) subq_38 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity__plan0.sql new file mode 100644 index 0000000000..1f646bdb7d --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity__plan0.sql @@ -0,0 +1,422 @@ +-- Compute Metrics via Expressions +SELECT + subq_18.metric_time__martian_day + , CAST(subq_18.buys AS DOUBLE PRECISION) / CAST(NULLIF(subq_18.visits, 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_5.visits) AS visits + , MAX(subq_17.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_4.metric_time__martian_day + , SUM(subq_4.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_3.metric_time__martian_day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + ) subq_4 + GROUP BY + subq_4.metric_time__martian_day + ) subq_5 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_16.metric_time__martian_day + , SUM(subq_16.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_15.metric_time__martian_day + , subq_15.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_14.metric_time__martian_day + , subq_14.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_13.metric_time__martian_day + , subq_13.ds__day + , subq_13.metric_time__day + , subq_13.user + , subq_13.buys + , subq_13.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_9.visits) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_9.metric_time__martian_day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_9.ds__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_9.metric_time__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_9.user) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_12.mf_internal_uuid AS mf_internal_uuid + , subq_12.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_8.metric_time__martian_day + , subq_8.ds__day + , subq_8.metric_time__day + , subq_8.user + , subq_8.visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_6.ds__day AS ds__day + , subq_6.ds__week AS ds__week + , subq_6.ds__month AS ds__month + , subq_6.ds__quarter AS ds__quarter + , subq_6.ds__year AS ds__year + , subq_6.ds__extract_year AS ds__extract_year + , subq_6.ds__extract_quarter AS ds__extract_quarter + , subq_6.ds__extract_month AS ds__extract_month + , subq_6.ds__extract_day AS ds__extract_day + , subq_6.ds__extract_dow AS ds__extract_dow + , subq_6.ds__extract_doy AS ds__extract_doy + , subq_6.visit__ds__day AS visit__ds__day + , subq_6.visit__ds__week AS visit__ds__week + , subq_6.visit__ds__month AS visit__ds__month + , subq_6.visit__ds__quarter AS visit__ds__quarter + , subq_6.visit__ds__year AS visit__ds__year + , subq_6.visit__ds__extract_year AS visit__ds__extract_year + , subq_6.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_6.visit__ds__extract_month AS visit__ds__extract_month + , subq_6.visit__ds__extract_day AS visit__ds__extract_day + , subq_6.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_6.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_6.ds__day AS metric_time__day + , subq_6.ds__week AS metric_time__week + , subq_6.ds__month AS metric_time__month + , subq_6.ds__quarter AS metric_time__quarter + , subq_6.ds__year AS metric_time__year + , subq_6.ds__extract_year AS metric_time__extract_year + , subq_6.ds__extract_quarter AS metric_time__extract_quarter + , subq_6.ds__extract_month AS metric_time__extract_month + , subq_6.ds__extract_day AS metric_time__extract_day + , subq_6.ds__extract_dow AS metric_time__extract_dow + , subq_6.ds__extract_doy AS metric_time__extract_doy + , subq_6.user AS user + , subq_6.session AS session + , subq_6.visit__user AS visit__user + , subq_6.visit__session AS visit__session + , subq_6.referrer_id AS referrer_id + , subq_6.visit__referrer_id AS visit__referrer_id + , subq_6.visits AS visits + , subq_6.visitors AS visitors + , subq_7.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_6 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_7 + ON + subq_6.ds__day = subq_7.ds + ) subq_8 + ) subq_9 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_11.ds__day + , subq_11.ds__week + , subq_11.ds__month + , subq_11.ds__quarter + , subq_11.ds__year + , subq_11.ds__extract_year + , subq_11.ds__extract_quarter + , subq_11.ds__extract_month + , subq_11.ds__extract_day + , subq_11.ds__extract_dow + , subq_11.ds__extract_doy + , subq_11.buy__ds__day + , subq_11.buy__ds__week + , subq_11.buy__ds__month + , subq_11.buy__ds__quarter + , subq_11.buy__ds__year + , subq_11.buy__ds__extract_year + , subq_11.buy__ds__extract_quarter + , subq_11.buy__ds__extract_month + , subq_11.buy__ds__extract_day + , subq_11.buy__ds__extract_dow + , subq_11.buy__ds__extract_doy + , subq_11.metric_time__day + , subq_11.metric_time__week + , subq_11.metric_time__month + , subq_11.metric_time__quarter + , subq_11.metric_time__year + , subq_11.metric_time__extract_year + , subq_11.metric_time__extract_quarter + , subq_11.metric_time__extract_month + , subq_11.metric_time__extract_day + , subq_11.metric_time__extract_dow + , subq_11.metric_time__extract_doy + , subq_11.user + , subq_11.session_id + , subq_11.buy__user + , subq_11.buy__session_id + , subq_11.buys + , subq_11.buyers + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_10.ds__day + , subq_10.ds__week + , subq_10.ds__month + , subq_10.ds__quarter + , subq_10.ds__year + , subq_10.ds__extract_year + , subq_10.ds__extract_quarter + , subq_10.ds__extract_month + , subq_10.ds__extract_day + , subq_10.ds__extract_dow + , subq_10.ds__extract_doy + , subq_10.buy__ds__day + , subq_10.buy__ds__week + , subq_10.buy__ds__month + , subq_10.buy__ds__quarter + , subq_10.buy__ds__year + , subq_10.buy__ds__extract_year + , subq_10.buy__ds__extract_quarter + , subq_10.buy__ds__extract_month + , subq_10.buy__ds__extract_day + , subq_10.buy__ds__extract_dow + , subq_10.buy__ds__extract_doy + , subq_10.ds__day AS metric_time__day + , subq_10.ds__week AS metric_time__week + , subq_10.ds__month AS metric_time__month + , subq_10.ds__quarter AS metric_time__quarter + , subq_10.ds__year AS metric_time__year + , subq_10.ds__extract_year AS metric_time__extract_year + , subq_10.ds__extract_quarter AS metric_time__extract_quarter + , subq_10.ds__extract_month AS metric_time__extract_month + , subq_10.ds__extract_day AS metric_time__extract_day + , subq_10.ds__extract_dow AS metric_time__extract_dow + , subq_10.ds__extract_doy AS metric_time__extract_doy + , subq_10.user + , subq_10.session_id + , subq_10.buy__user + , subq_10.buy__session_id + , subq_10.buys + , subq_10.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_10 + ) subq_11 + ) subq_12 + ON + ( + subq_9.user = subq_12.user + ) AND ( + ( + subq_9.ds__day <= subq_12.ds__day + ) AND ( + subq_9.ds__day > subq_12.ds__day - MAKE_INTERVAL(days => 7) + ) + ) + ) subq_13 + ) subq_14 + ) subq_15 + ) subq_16 + GROUP BY + subq_16.metric_time__martian_day + ) subq_17 + ON + subq_5.metric_time__martian_day = subq_17.metric_time__martian_day + GROUP BY + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) +) subq_18 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity__plan0_optimized.sql new file mode 100644 index 0000000000..88fef2bdf6 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity__plan0_optimized.sql @@ -0,0 +1,139 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE PRECISION) / CAST(NULLIF(visits, 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_24.visits) AS visits + , MAX(subq_36.buys) AS buys + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + subq_21.martian_day AS metric_time__martian_day + , SUM(subq_20.visits) AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_20 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_21 + ON + subq_20.metric_time__day = subq_21.ds + GROUP BY + subq_21.martian_day + ) subq_24 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_28.visits) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_28.metric_time__martian_day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_28.ds__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_28.metric_time__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_28.user) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_31.mf_internal_uuid AS mf_internal_uuid + , subq_31.buys AS buys + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_26.martian_day AS metric_time__martian_day + , subq_25.ds__day AS ds__day + , subq_25.ds__day AS metric_time__day + , subq_25.user AS user + , subq_25.visits AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_25 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_26 + ON + subq_25.ds__day = subq_26.ds + ) subq_28 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_31 + ON + ( + subq_28.user = subq_31.user + ) AND ( + ( + subq_28.ds__day <= subq_31.ds__day + ) AND ( + subq_28.ds__day > subq_31.ds__day - MAKE_INTERVAL(days => 7) + ) + ) + ) subq_32 + GROUP BY + metric_time__martian_day + ) subq_36 + ON + subq_24.metric_time__martian_day = subq_36.metric_time__martian_day + GROUP BY + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) +) subq_37 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter__plan0.sql new file mode 100644 index 0000000000..85d948d448 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter__plan0.sql @@ -0,0 +1,477 @@ +-- Compute Metrics via Expressions +SELECT + subq_20.metric_time__martian_day + , CAST(subq_20.buys AS DOUBLE PRECISION) / CAST(NULLIF(subq_20.visits, 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_6.visits) AS visits + , MAX(subq_19.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__martian_day + , SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_4.metric_time__martian_day + , subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + GROUP BY + subq_5.metric_time__martian_day + ) subq_6 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_18.metric_time__martian_day + , SUM(subq_18.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_17.metric_time__martian_day + , subq_17.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_16.metric_time__martian_day + , subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > subq_14.ds__day - MAKE_INTERVAL(days => 7) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 + GROUP BY + subq_18.metric_time__martian_day + ) subq_19 + ON + subq_6.metric_time__martian_day = subq_19.metric_time__martian_day + GROUP BY + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) +) subq_20 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql new file mode 100644 index 0000000000..4fab341eb9 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql @@ -0,0 +1,156 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE PRECISION) / CAST(NULLIF(visits, 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_27.visits) AS visits + , MAX(subq_40.buys) AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_22.visits AS visits + , subq_23.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_22 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_23 + ON + subq_22.metric_time__day = subq_23.ds + ) subq_24 + WHERE metric_time__martian_day = '2020-01-01' + GROUP BY + metric_time__martian_day + ) subq_27 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_32.visits) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_32.metric_time__martian_day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_32.ds__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_32.metric_time__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_32.user) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_35.mf_internal_uuid AS mf_internal_uuid + , subq_35.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_30.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_28.ds__day AS ds__day + , subq_28.ds__day AS metric_time__day + , subq_28.user AS user + , subq_28.visits AS visits + , subq_29.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_28 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_29 + ON + subq_28.ds__day = subq_29.ds + ) subq_30 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_32 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_35 + ON + ( + subq_32.user = subq_35.user + ) AND ( + ( + subq_32.ds__day <= subq_35.ds__day + ) AND ( + subq_32.ds__day > subq_35.ds__day - MAKE_INTERVAL(days => 7) + ) + ) + ) subq_36 + GROUP BY + metric_time__martian_day + ) subq_40 + ON + subq_27.metric_time__martian_day = subq_40.metric_time__martian_day + GROUP BY + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) +) subq_41 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql new file mode 100644 index 0000000000..4a9494a2fe --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql @@ -0,0 +1,457 @@ +-- Compute Metrics via Expressions +SELECT + CAST(subq_19.buys AS DOUBLE PRECISION) / CAST(NULLIF(subq_19.visits, 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + MAX(subq_6.visits) AS visits + , MAX(subq_18.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits',] + SELECT + subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + CROSS JOIN ( + -- Aggregate Measures + SELECT + SUM(subq_17.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys',] + SELECT + subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(isodow FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(isodow FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > subq_14.ds__day - MAKE_INTERVAL(days => 7) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 +) subq_19 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql new file mode 100644 index 0000000000..7c8db0a39b --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Postgres/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql @@ -0,0 +1,138 @@ +-- Combine Aggregated Outputs +-- Compute Metrics via Expressions +SELECT + CAST(MAX(subq_38.buys) AS DOUBLE PRECISION) / CAST(NULLIF(MAX(subq_26.visits), 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits',] + -- Aggregate Measures + SELECT + SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_21.visits AS visits + , subq_22.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_21 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_22 + ON + subq_21.metric_time__day = subq_22.ds + ) subq_23 + WHERE metric_time__martian_day = '2020-01-01' +) subq_26 +CROSS JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys',] + -- Aggregate Measures + SELECT + SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_31.visits) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_31.metric_time__martian_day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_31.ds__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_31.metric_time__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_31.user) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_34.mf_internal_uuid AS mf_internal_uuid + , subq_34.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_29.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_27.ds__day AS ds__day + , subq_27.ds__day AS metric_time__day + , subq_27.user AS user + , subq_27.visits AS visits + , subq_28.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_27 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_28 + ON + subq_27.ds__day = subq_28.ds + ) subq_29 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_31 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , GEN_RANDOM_UUID() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_34 + ON + ( + subq_31.user = subq_34.user + ) AND ( + ( + subq_31.ds__day <= subq_34.ds__day + ) AND ( + subq_31.ds__day > subq_34.ds__day - MAKE_INTERVAL(days => 7) + ) + ) + ) subq_35 +) subq_38 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity__plan0.sql new file mode 100644 index 0000000000..0b73257cd1 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity__plan0.sql @@ -0,0 +1,422 @@ +-- Compute Metrics via Expressions +SELECT + subq_18.metric_time__martian_day + , CAST(subq_18.buys AS DOUBLE PRECISION) / CAST(NULLIF(subq_18.visits, 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_5.visits) AS visits + , MAX(subq_17.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_4.metric_time__martian_day + , SUM(subq_4.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_3.metric_time__martian_day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + ) subq_4 + GROUP BY + subq_4.metric_time__martian_day + ) subq_5 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_16.metric_time__martian_day + , SUM(subq_16.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_15.metric_time__martian_day + , subq_15.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_14.metric_time__martian_day + , subq_14.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_13.metric_time__martian_day + , subq_13.ds__day + , subq_13.metric_time__day + , subq_13.user + , subq_13.buys + , subq_13.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_9.visits) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_9.metric_time__martian_day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_9.ds__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_9.metric_time__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_9.user) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_12.mf_internal_uuid AS mf_internal_uuid + , subq_12.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_8.metric_time__martian_day + , subq_8.ds__day + , subq_8.metric_time__day + , subq_8.user + , subq_8.visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_6.ds__day AS ds__day + , subq_6.ds__week AS ds__week + , subq_6.ds__month AS ds__month + , subq_6.ds__quarter AS ds__quarter + , subq_6.ds__year AS ds__year + , subq_6.ds__extract_year AS ds__extract_year + , subq_6.ds__extract_quarter AS ds__extract_quarter + , subq_6.ds__extract_month AS ds__extract_month + , subq_6.ds__extract_day AS ds__extract_day + , subq_6.ds__extract_dow AS ds__extract_dow + , subq_6.ds__extract_doy AS ds__extract_doy + , subq_6.visit__ds__day AS visit__ds__day + , subq_6.visit__ds__week AS visit__ds__week + , subq_6.visit__ds__month AS visit__ds__month + , subq_6.visit__ds__quarter AS visit__ds__quarter + , subq_6.visit__ds__year AS visit__ds__year + , subq_6.visit__ds__extract_year AS visit__ds__extract_year + , subq_6.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_6.visit__ds__extract_month AS visit__ds__extract_month + , subq_6.visit__ds__extract_day AS visit__ds__extract_day + , subq_6.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_6.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_6.ds__day AS metric_time__day + , subq_6.ds__week AS metric_time__week + , subq_6.ds__month AS metric_time__month + , subq_6.ds__quarter AS metric_time__quarter + , subq_6.ds__year AS metric_time__year + , subq_6.ds__extract_year AS metric_time__extract_year + , subq_6.ds__extract_quarter AS metric_time__extract_quarter + , subq_6.ds__extract_month AS metric_time__extract_month + , subq_6.ds__extract_day AS metric_time__extract_day + , subq_6.ds__extract_dow AS metric_time__extract_dow + , subq_6.ds__extract_doy AS metric_time__extract_doy + , subq_6.user AS user + , subq_6.session AS session + , subq_6.visit__user AS visit__user + , subq_6.visit__session AS visit__session + , subq_6.referrer_id AS referrer_id + , subq_6.visit__referrer_id AS visit__referrer_id + , subq_6.visits AS visits + , subq_6.visitors AS visitors + , subq_7.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_6 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_7 + ON + subq_6.ds__day = subq_7.ds + ) subq_8 + ) subq_9 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_11.ds__day + , subq_11.ds__week + , subq_11.ds__month + , subq_11.ds__quarter + , subq_11.ds__year + , subq_11.ds__extract_year + , subq_11.ds__extract_quarter + , subq_11.ds__extract_month + , subq_11.ds__extract_day + , subq_11.ds__extract_dow + , subq_11.ds__extract_doy + , subq_11.buy__ds__day + , subq_11.buy__ds__week + , subq_11.buy__ds__month + , subq_11.buy__ds__quarter + , subq_11.buy__ds__year + , subq_11.buy__ds__extract_year + , subq_11.buy__ds__extract_quarter + , subq_11.buy__ds__extract_month + , subq_11.buy__ds__extract_day + , subq_11.buy__ds__extract_dow + , subq_11.buy__ds__extract_doy + , subq_11.metric_time__day + , subq_11.metric_time__week + , subq_11.metric_time__month + , subq_11.metric_time__quarter + , subq_11.metric_time__year + , subq_11.metric_time__extract_year + , subq_11.metric_time__extract_quarter + , subq_11.metric_time__extract_month + , subq_11.metric_time__extract_day + , subq_11.metric_time__extract_dow + , subq_11.metric_time__extract_doy + , subq_11.user + , subq_11.session_id + , subq_11.buy__user + , subq_11.buy__session_id + , subq_11.buys + , subq_11.buyers + , CONCAT(CAST(RANDOM()*100000000 AS INT)::VARCHAR,CAST(RANDOM()*100000000 AS INT)::VARCHAR) AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_10.ds__day + , subq_10.ds__week + , subq_10.ds__month + , subq_10.ds__quarter + , subq_10.ds__year + , subq_10.ds__extract_year + , subq_10.ds__extract_quarter + , subq_10.ds__extract_month + , subq_10.ds__extract_day + , subq_10.ds__extract_dow + , subq_10.ds__extract_doy + , subq_10.buy__ds__day + , subq_10.buy__ds__week + , subq_10.buy__ds__month + , subq_10.buy__ds__quarter + , subq_10.buy__ds__year + , subq_10.buy__ds__extract_year + , subq_10.buy__ds__extract_quarter + , subq_10.buy__ds__extract_month + , subq_10.buy__ds__extract_day + , subq_10.buy__ds__extract_dow + , subq_10.buy__ds__extract_doy + , subq_10.ds__day AS metric_time__day + , subq_10.ds__week AS metric_time__week + , subq_10.ds__month AS metric_time__month + , subq_10.ds__quarter AS metric_time__quarter + , subq_10.ds__year AS metric_time__year + , subq_10.ds__extract_year AS metric_time__extract_year + , subq_10.ds__extract_quarter AS metric_time__extract_quarter + , subq_10.ds__extract_month AS metric_time__extract_month + , subq_10.ds__extract_day AS metric_time__extract_day + , subq_10.ds__extract_dow AS metric_time__extract_dow + , subq_10.ds__extract_doy AS metric_time__extract_doy + , subq_10.user + , subq_10.session_id + , subq_10.buy__user + , subq_10.buy__session_id + , subq_10.buys + , subq_10.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , CASE WHEN EXTRACT(dow FROM buys_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM buys_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM buys_source_src_28000.ds) END AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , CASE WHEN EXTRACT(dow FROM buys_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM buys_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM buys_source_src_28000.ds) END AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_10 + ) subq_11 + ) subq_12 + ON + ( + subq_9.user = subq_12.user + ) AND ( + ( + subq_9.ds__day <= subq_12.ds__day + ) AND ( + subq_9.ds__day > DATEADD(day, -7, subq_12.ds__day) + ) + ) + ) subq_13 + ) subq_14 + ) subq_15 + ) subq_16 + GROUP BY + subq_16.metric_time__martian_day + ) subq_17 + ON + subq_5.metric_time__martian_day = subq_17.metric_time__martian_day + GROUP BY + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) +) subq_18 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity__plan0_optimized.sql new file mode 100644 index 0000000000..e828f19ced --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity__plan0_optimized.sql @@ -0,0 +1,139 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE PRECISION) / CAST(NULLIF(visits, 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_24.visits) AS visits + , MAX(subq_36.buys) AS buys + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + subq_21.martian_day AS metric_time__martian_day + , SUM(subq_20.visits) AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_20 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_21 + ON + subq_20.metric_time__day = subq_21.ds + GROUP BY + subq_21.martian_day + ) subq_24 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_28.visits) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_28.metric_time__martian_day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_28.ds__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_28.metric_time__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_28.user) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_31.mf_internal_uuid AS mf_internal_uuid + , subq_31.buys AS buys + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_26.martian_day AS metric_time__martian_day + , subq_25.ds__day AS ds__day + , subq_25.ds__day AS metric_time__day + , subq_25.user AS user + , subq_25.visits AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_25 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_26 + ON + subq_25.ds__day = subq_26.ds + ) subq_28 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , CONCAT(CAST(RANDOM()*100000000 AS INT)::VARCHAR,CAST(RANDOM()*100000000 AS INT)::VARCHAR) AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_31 + ON + ( + subq_28.user = subq_31.user + ) AND ( + ( + subq_28.ds__day <= subq_31.ds__day + ) AND ( + subq_28.ds__day > DATEADD(day, -7, subq_31.ds__day) + ) + ) + ) subq_32 + GROUP BY + metric_time__martian_day + ) subq_36 + ON + subq_24.metric_time__martian_day = subq_36.metric_time__martian_day + GROUP BY + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) +) subq_37 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter__plan0.sql new file mode 100644 index 0000000000..72e5b62823 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter__plan0.sql @@ -0,0 +1,477 @@ +-- Compute Metrics via Expressions +SELECT + subq_20.metric_time__martian_day + , CAST(subq_20.buys AS DOUBLE PRECISION) / CAST(NULLIF(subq_20.visits, 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_6.visits) AS visits + , MAX(subq_19.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__martian_day + , SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_4.metric_time__martian_day + , subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + GROUP BY + subq_5.metric_time__martian_day + ) subq_6 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_18.metric_time__martian_day + , SUM(subq_18.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_17.metric_time__martian_day + , subq_17.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_16.metric_time__martian_day + , subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , CONCAT(CAST(RANDOM()*100000000 AS INT)::VARCHAR,CAST(RANDOM()*100000000 AS INT)::VARCHAR) AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , CASE WHEN EXTRACT(dow FROM buys_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM buys_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM buys_source_src_28000.ds) END AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , CASE WHEN EXTRACT(dow FROM buys_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM buys_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM buys_source_src_28000.ds) END AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > DATEADD(day, -7, subq_14.ds__day) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 + GROUP BY + subq_18.metric_time__martian_day + ) subq_19 + ON + subq_6.metric_time__martian_day = subq_19.metric_time__martian_day + GROUP BY + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) +) subq_20 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql new file mode 100644 index 0000000000..136d6b62a9 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql @@ -0,0 +1,156 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE PRECISION) / CAST(NULLIF(visits, 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_27.visits) AS visits + , MAX(subq_40.buys) AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_22.visits AS visits + , subq_23.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_22 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_23 + ON + subq_22.metric_time__day = subq_23.ds + ) subq_24 + WHERE metric_time__martian_day = '2020-01-01' + GROUP BY + metric_time__martian_day + ) subq_27 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_32.visits) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_32.metric_time__martian_day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_32.ds__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_32.metric_time__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_32.user) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_35.mf_internal_uuid AS mf_internal_uuid + , subq_35.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_30.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_28.ds__day AS ds__day + , subq_28.ds__day AS metric_time__day + , subq_28.user AS user + , subq_28.visits AS visits + , subq_29.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_28 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_29 + ON + subq_28.ds__day = subq_29.ds + ) subq_30 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_32 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , CONCAT(CAST(RANDOM()*100000000 AS INT)::VARCHAR,CAST(RANDOM()*100000000 AS INT)::VARCHAR) AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_35 + ON + ( + subq_32.user = subq_35.user + ) AND ( + ( + subq_32.ds__day <= subq_35.ds__day + ) AND ( + subq_32.ds__day > DATEADD(day, -7, subq_35.ds__day) + ) + ) + ) subq_36 + GROUP BY + metric_time__martian_day + ) subq_40 + ON + subq_27.metric_time__martian_day = subq_40.metric_time__martian_day + GROUP BY + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) +) subq_41 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql new file mode 100644 index 0000000000..275f71855e --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql @@ -0,0 +1,457 @@ +-- Compute Metrics via Expressions +SELECT + CAST(subq_19.buys AS DOUBLE PRECISION) / CAST(NULLIF(subq_19.visits, 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + MAX(subq_6.visits) AS visits + , MAX(subq_18.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits',] + SELECT + subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + CROSS JOIN ( + -- Aggregate Measures + SELECT + SUM(subq_17.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys',] + SELECT + subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , CASE WHEN EXTRACT(dow FROM visits_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM visits_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM visits_source_src_28000.ds) END AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , CONCAT(CAST(RANDOM()*100000000 AS INT)::VARCHAR,CAST(RANDOM()*100000000 AS INT)::VARCHAR) AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , CASE WHEN EXTRACT(dow FROM buys_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM buys_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM buys_source_src_28000.ds) END AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , CASE WHEN EXTRACT(dow FROM buys_source_src_28000.ds) = 0 THEN EXTRACT(dow FROM buys_source_src_28000.ds) + 7 ELSE EXTRACT(dow FROM buys_source_src_28000.ds) END AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > DATEADD(day, -7, subq_14.ds__day) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 +) subq_19 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql new file mode 100644 index 0000000000..5dcf601858 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Redshift/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql @@ -0,0 +1,138 @@ +-- Combine Aggregated Outputs +-- Compute Metrics via Expressions +SELECT + CAST(MAX(subq_38.buys) AS DOUBLE PRECISION) / CAST(NULLIF(MAX(subq_26.visits), 0) AS DOUBLE PRECISION) AS visit_buy_conversion_rate_7days +FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits',] + -- Aggregate Measures + SELECT + SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_21.visits AS visits + , subq_22.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_21 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_22 + ON + subq_21.metric_time__day = subq_22.ds + ) subq_23 + WHERE metric_time__martian_day = '2020-01-01' +) subq_26 +CROSS JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys',] + -- Aggregate Measures + SELECT + SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_31.visits) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_31.metric_time__martian_day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_31.ds__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_31.metric_time__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_31.user) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_34.mf_internal_uuid AS mf_internal_uuid + , subq_34.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_29.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_27.ds__day AS ds__day + , subq_27.ds__day AS metric_time__day + , subq_27.user AS user + , subq_27.visits AS visits + , subq_28.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_27 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_28 + ON + subq_27.ds__day = subq_28.ds + ) subq_29 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_31 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , CONCAT(CAST(RANDOM()*100000000 AS INT)::VARCHAR,CAST(RANDOM()*100000000 AS INT)::VARCHAR) AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_34 + ON + ( + subq_31.user = subq_34.user + ) AND ( + ( + subq_31.ds__day <= subq_34.ds__day + ) AND ( + subq_31.ds__day > DATEADD(day, -7, subq_34.ds__day) + ) + ) + ) subq_35 +) subq_38 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity__plan0.sql new file mode 100644 index 0000000000..c033f92a2f --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity__plan0.sql @@ -0,0 +1,422 @@ +-- Compute Metrics via Expressions +SELECT + subq_18.metric_time__martian_day + , CAST(subq_18.buys AS DOUBLE) / CAST(NULLIF(subq_18.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_5.visits) AS visits + , MAX(subq_17.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_4.metric_time__martian_day + , SUM(subq_4.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_3.metric_time__martian_day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + ) subq_4 + GROUP BY + subq_4.metric_time__martian_day + ) subq_5 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_16.metric_time__martian_day + , SUM(subq_16.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_15.metric_time__martian_day + , subq_15.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_14.metric_time__martian_day + , subq_14.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_13.metric_time__martian_day + , subq_13.ds__day + , subq_13.metric_time__day + , subq_13.user + , subq_13.buys + , subq_13.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_9.visits) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_9.metric_time__martian_day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_9.ds__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_9.metric_time__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_9.user) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_12.mf_internal_uuid AS mf_internal_uuid + , subq_12.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_8.metric_time__martian_day + , subq_8.ds__day + , subq_8.metric_time__day + , subq_8.user + , subq_8.visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_6.ds__day AS ds__day + , subq_6.ds__week AS ds__week + , subq_6.ds__month AS ds__month + , subq_6.ds__quarter AS ds__quarter + , subq_6.ds__year AS ds__year + , subq_6.ds__extract_year AS ds__extract_year + , subq_6.ds__extract_quarter AS ds__extract_quarter + , subq_6.ds__extract_month AS ds__extract_month + , subq_6.ds__extract_day AS ds__extract_day + , subq_6.ds__extract_dow AS ds__extract_dow + , subq_6.ds__extract_doy AS ds__extract_doy + , subq_6.visit__ds__day AS visit__ds__day + , subq_6.visit__ds__week AS visit__ds__week + , subq_6.visit__ds__month AS visit__ds__month + , subq_6.visit__ds__quarter AS visit__ds__quarter + , subq_6.visit__ds__year AS visit__ds__year + , subq_6.visit__ds__extract_year AS visit__ds__extract_year + , subq_6.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_6.visit__ds__extract_month AS visit__ds__extract_month + , subq_6.visit__ds__extract_day AS visit__ds__extract_day + , subq_6.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_6.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_6.ds__day AS metric_time__day + , subq_6.ds__week AS metric_time__week + , subq_6.ds__month AS metric_time__month + , subq_6.ds__quarter AS metric_time__quarter + , subq_6.ds__year AS metric_time__year + , subq_6.ds__extract_year AS metric_time__extract_year + , subq_6.ds__extract_quarter AS metric_time__extract_quarter + , subq_6.ds__extract_month AS metric_time__extract_month + , subq_6.ds__extract_day AS metric_time__extract_day + , subq_6.ds__extract_dow AS metric_time__extract_dow + , subq_6.ds__extract_doy AS metric_time__extract_doy + , subq_6.user AS user + , subq_6.session AS session + , subq_6.visit__user AS visit__user + , subq_6.visit__session AS visit__session + , subq_6.referrer_id AS referrer_id + , subq_6.visit__referrer_id AS visit__referrer_id + , subq_6.visits AS visits + , subq_6.visitors AS visitors + , subq_7.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_6 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_7 + ON + subq_6.ds__day = subq_7.ds + ) subq_8 + ) subq_9 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_11.ds__day + , subq_11.ds__week + , subq_11.ds__month + , subq_11.ds__quarter + , subq_11.ds__year + , subq_11.ds__extract_year + , subq_11.ds__extract_quarter + , subq_11.ds__extract_month + , subq_11.ds__extract_day + , subq_11.ds__extract_dow + , subq_11.ds__extract_doy + , subq_11.buy__ds__day + , subq_11.buy__ds__week + , subq_11.buy__ds__month + , subq_11.buy__ds__quarter + , subq_11.buy__ds__year + , subq_11.buy__ds__extract_year + , subq_11.buy__ds__extract_quarter + , subq_11.buy__ds__extract_month + , subq_11.buy__ds__extract_day + , subq_11.buy__ds__extract_dow + , subq_11.buy__ds__extract_doy + , subq_11.metric_time__day + , subq_11.metric_time__week + , subq_11.metric_time__month + , subq_11.metric_time__quarter + , subq_11.metric_time__year + , subq_11.metric_time__extract_year + , subq_11.metric_time__extract_quarter + , subq_11.metric_time__extract_month + , subq_11.metric_time__extract_day + , subq_11.metric_time__extract_dow + , subq_11.metric_time__extract_doy + , subq_11.user + , subq_11.session_id + , subq_11.buy__user + , subq_11.buy__session_id + , subq_11.buys + , subq_11.buyers + , UUID_STRING() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_10.ds__day + , subq_10.ds__week + , subq_10.ds__month + , subq_10.ds__quarter + , subq_10.ds__year + , subq_10.ds__extract_year + , subq_10.ds__extract_quarter + , subq_10.ds__extract_month + , subq_10.ds__extract_day + , subq_10.ds__extract_dow + , subq_10.ds__extract_doy + , subq_10.buy__ds__day + , subq_10.buy__ds__week + , subq_10.buy__ds__month + , subq_10.buy__ds__quarter + , subq_10.buy__ds__year + , subq_10.buy__ds__extract_year + , subq_10.buy__ds__extract_quarter + , subq_10.buy__ds__extract_month + , subq_10.buy__ds__extract_day + , subq_10.buy__ds__extract_dow + , subq_10.buy__ds__extract_doy + , subq_10.ds__day AS metric_time__day + , subq_10.ds__week AS metric_time__week + , subq_10.ds__month AS metric_time__month + , subq_10.ds__quarter AS metric_time__quarter + , subq_10.ds__year AS metric_time__year + , subq_10.ds__extract_year AS metric_time__extract_year + , subq_10.ds__extract_quarter AS metric_time__extract_quarter + , subq_10.ds__extract_month AS metric_time__extract_month + , subq_10.ds__extract_day AS metric_time__extract_day + , subq_10.ds__extract_dow AS metric_time__extract_dow + , subq_10.ds__extract_doy AS metric_time__extract_doy + , subq_10.user + , subq_10.session_id + , subq_10.buy__user + , subq_10.buy__session_id + , subq_10.buys + , subq_10.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(dayofweekiso FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(dayofweekiso FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_10 + ) subq_11 + ) subq_12 + ON + ( + subq_9.user = subq_12.user + ) AND ( + ( + subq_9.ds__day <= subq_12.ds__day + ) AND ( + subq_9.ds__day > DATEADD(day, -7, subq_12.ds__day) + ) + ) + ) subq_13 + ) subq_14 + ) subq_15 + ) subq_16 + GROUP BY + subq_16.metric_time__martian_day + ) subq_17 + ON + subq_5.metric_time__martian_day = subq_17.metric_time__martian_day + GROUP BY + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) +) subq_18 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity__plan0_optimized.sql new file mode 100644 index 0000000000..2761818e64 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity__plan0_optimized.sql @@ -0,0 +1,139 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE) / CAST(NULLIF(visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_24.visits) AS visits + , MAX(subq_36.buys) AS buys + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + subq_21.martian_day AS metric_time__martian_day + , SUM(subq_20.visits) AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_20 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_21 + ON + subq_20.metric_time__day = subq_21.ds + GROUP BY + subq_21.martian_day + ) subq_24 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_28.visits) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_28.metric_time__martian_day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_28.ds__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_28.metric_time__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_28.user) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_31.mf_internal_uuid AS mf_internal_uuid + , subq_31.buys AS buys + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_26.martian_day AS metric_time__martian_day + , subq_25.ds__day AS ds__day + , subq_25.ds__day AS metric_time__day + , subq_25.user AS user + , subq_25.visits AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_25 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_26 + ON + subq_25.ds__day = subq_26.ds + ) subq_28 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , UUID_STRING() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_31 + ON + ( + subq_28.user = subq_31.user + ) AND ( + ( + subq_28.ds__day <= subq_31.ds__day + ) AND ( + subq_28.ds__day > DATEADD(day, -7, subq_31.ds__day) + ) + ) + ) subq_32 + GROUP BY + metric_time__martian_day + ) subq_36 + ON + subq_24.metric_time__martian_day = subq_36.metric_time__martian_day + GROUP BY + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) +) subq_37 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter__plan0.sql new file mode 100644 index 0000000000..515a1b4f2d --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter__plan0.sql @@ -0,0 +1,477 @@ +-- Compute Metrics via Expressions +SELECT + subq_20.metric_time__martian_day + , CAST(subq_20.buys AS DOUBLE) / CAST(NULLIF(subq_20.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_6.visits) AS visits + , MAX(subq_19.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__martian_day + , SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_4.metric_time__martian_day + , subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + GROUP BY + subq_5.metric_time__martian_day + ) subq_6 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_18.metric_time__martian_day + , SUM(subq_18.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_17.metric_time__martian_day + , subq_17.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_16.metric_time__martian_day + , subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , UUID_STRING() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(dayofweekiso FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(dayofweekiso FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > DATEADD(day, -7, subq_14.ds__day) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 + GROUP BY + subq_18.metric_time__martian_day + ) subq_19 + ON + subq_6.metric_time__martian_day = subq_19.metric_time__martian_day + GROUP BY + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) +) subq_20 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql new file mode 100644 index 0000000000..c3fd047e6b --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql @@ -0,0 +1,156 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE) / CAST(NULLIF(visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_27.visits) AS visits + , MAX(subq_40.buys) AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_22.visits AS visits + , subq_23.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_22 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_23 + ON + subq_22.metric_time__day = subq_23.ds + ) subq_24 + WHERE metric_time__martian_day = '2020-01-01' + GROUP BY + metric_time__martian_day + ) subq_27 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_32.visits) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_32.metric_time__martian_day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_32.ds__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_32.metric_time__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_32.user) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_35.mf_internal_uuid AS mf_internal_uuid + , subq_35.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_30.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_28.ds__day AS ds__day + , subq_28.ds__day AS metric_time__day + , subq_28.user AS user + , subq_28.visits AS visits + , subq_29.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_28 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_29 + ON + subq_28.ds__day = subq_29.ds + ) subq_30 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_32 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , UUID_STRING() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_35 + ON + ( + subq_32.user = subq_35.user + ) AND ( + ( + subq_32.ds__day <= subq_35.ds__day + ) AND ( + subq_32.ds__day > DATEADD(day, -7, subq_35.ds__day) + ) + ) + ) subq_36 + GROUP BY + metric_time__martian_day + ) subq_40 + ON + subq_27.metric_time__martian_day = subq_40.metric_time__martian_day + GROUP BY + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) +) subq_41 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql new file mode 100644 index 0000000000..6166740f36 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql @@ -0,0 +1,457 @@ +-- Compute Metrics via Expressions +SELECT + CAST(subq_19.buys AS DOUBLE) / CAST(NULLIF(subq_19.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + MAX(subq_6.visits) AS visits + , MAX(subq_18.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits',] + SELECT + subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + CROSS JOIN ( + -- Aggregate Measures + SELECT + SUM(subq_17.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys',] + SELECT + subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(dayofweekiso FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , UUID_STRING() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(dayofweekiso FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(dayofweekiso FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > DATEADD(day, -7, subq_14.ds__day) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 +) subq_19 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql new file mode 100644 index 0000000000..d2cd29df37 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Snowflake/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql @@ -0,0 +1,138 @@ +-- Combine Aggregated Outputs +-- Compute Metrics via Expressions +SELECT + CAST(MAX(subq_38.buys) AS DOUBLE) / CAST(NULLIF(MAX(subq_26.visits), 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits',] + -- Aggregate Measures + SELECT + SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_21.visits AS visits + , subq_22.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_21 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_22 + ON + subq_21.metric_time__day = subq_22.ds + ) subq_23 + WHERE metric_time__martian_day = '2020-01-01' +) subq_26 +CROSS JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys',] + -- Aggregate Measures + SELECT + SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_31.visits) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_31.metric_time__martian_day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_31.ds__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_31.metric_time__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_31.user) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_34.mf_internal_uuid AS mf_internal_uuid + , subq_34.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_29.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_27.ds__day AS ds__day + , subq_27.ds__day AS metric_time__day + , subq_27.user AS user + , subq_27.visits AS visits + , subq_28.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_27 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_28 + ON + subq_27.ds__day = subq_28.ds + ) subq_29 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_31 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , UUID_STRING() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_34 + ON + ( + subq_31.user = subq_34.user + ) AND ( + ( + subq_31.ds__day <= subq_34.ds__day + ) AND ( + subq_31.ds__day > DATEADD(day, -7, subq_34.ds__day) + ) + ) + ) subq_35 +) subq_38 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity__plan0.sql new file mode 100644 index 0000000000..c932825a03 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity__plan0.sql @@ -0,0 +1,422 @@ +-- Compute Metrics via Expressions +SELECT + subq_18.metric_time__martian_day + , CAST(subq_18.buys AS DOUBLE) / CAST(NULLIF(subq_18.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_5.visits) AS visits + , MAX(subq_17.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_4.metric_time__martian_day + , SUM(subq_4.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_3.metric_time__martian_day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + ) subq_4 + GROUP BY + subq_4.metric_time__martian_day + ) subq_5 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_16.metric_time__martian_day + , SUM(subq_16.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_15.metric_time__martian_day + , subq_15.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_14.metric_time__martian_day + , subq_14.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_13.metric_time__martian_day + , subq_13.ds__day + , subq_13.metric_time__day + , subq_13.user + , subq_13.buys + , subq_13.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_9.visits) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_9.metric_time__martian_day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_9.ds__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_9.metric_time__day) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_9.user) OVER ( + PARTITION BY + subq_12.user + , subq_12.ds__day + , subq_12.mf_internal_uuid + ORDER BY subq_9.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_12.mf_internal_uuid AS mf_internal_uuid + , subq_12.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_8.metric_time__martian_day + , subq_8.ds__day + , subq_8.metric_time__day + , subq_8.user + , subq_8.visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_6.ds__day AS ds__day + , subq_6.ds__week AS ds__week + , subq_6.ds__month AS ds__month + , subq_6.ds__quarter AS ds__quarter + , subq_6.ds__year AS ds__year + , subq_6.ds__extract_year AS ds__extract_year + , subq_6.ds__extract_quarter AS ds__extract_quarter + , subq_6.ds__extract_month AS ds__extract_month + , subq_6.ds__extract_day AS ds__extract_day + , subq_6.ds__extract_dow AS ds__extract_dow + , subq_6.ds__extract_doy AS ds__extract_doy + , subq_6.visit__ds__day AS visit__ds__day + , subq_6.visit__ds__week AS visit__ds__week + , subq_6.visit__ds__month AS visit__ds__month + , subq_6.visit__ds__quarter AS visit__ds__quarter + , subq_6.visit__ds__year AS visit__ds__year + , subq_6.visit__ds__extract_year AS visit__ds__extract_year + , subq_6.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_6.visit__ds__extract_month AS visit__ds__extract_month + , subq_6.visit__ds__extract_day AS visit__ds__extract_day + , subq_6.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_6.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_6.ds__day AS metric_time__day + , subq_6.ds__week AS metric_time__week + , subq_6.ds__month AS metric_time__month + , subq_6.ds__quarter AS metric_time__quarter + , subq_6.ds__year AS metric_time__year + , subq_6.ds__extract_year AS metric_time__extract_year + , subq_6.ds__extract_quarter AS metric_time__extract_quarter + , subq_6.ds__extract_month AS metric_time__extract_month + , subq_6.ds__extract_day AS metric_time__extract_day + , subq_6.ds__extract_dow AS metric_time__extract_dow + , subq_6.ds__extract_doy AS metric_time__extract_doy + , subq_6.user AS user + , subq_6.session AS session + , subq_6.visit__user AS visit__user + , subq_6.visit__session AS visit__session + , subq_6.referrer_id AS referrer_id + , subq_6.visit__referrer_id AS visit__referrer_id + , subq_6.visits AS visits + , subq_6.visitors AS visitors + , subq_7.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_6 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_7 + ON + subq_6.ds__day = subq_7.ds + ) subq_8 + ) subq_9 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_11.ds__day + , subq_11.ds__week + , subq_11.ds__month + , subq_11.ds__quarter + , subq_11.ds__year + , subq_11.ds__extract_year + , subq_11.ds__extract_quarter + , subq_11.ds__extract_month + , subq_11.ds__extract_day + , subq_11.ds__extract_dow + , subq_11.ds__extract_doy + , subq_11.buy__ds__day + , subq_11.buy__ds__week + , subq_11.buy__ds__month + , subq_11.buy__ds__quarter + , subq_11.buy__ds__year + , subq_11.buy__ds__extract_year + , subq_11.buy__ds__extract_quarter + , subq_11.buy__ds__extract_month + , subq_11.buy__ds__extract_day + , subq_11.buy__ds__extract_dow + , subq_11.buy__ds__extract_doy + , subq_11.metric_time__day + , subq_11.metric_time__week + , subq_11.metric_time__month + , subq_11.metric_time__quarter + , subq_11.metric_time__year + , subq_11.metric_time__extract_year + , subq_11.metric_time__extract_quarter + , subq_11.metric_time__extract_month + , subq_11.metric_time__extract_day + , subq_11.metric_time__extract_dow + , subq_11.metric_time__extract_doy + , subq_11.user + , subq_11.session_id + , subq_11.buy__user + , subq_11.buy__session_id + , subq_11.buys + , subq_11.buyers + , uuid() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_10.ds__day + , subq_10.ds__week + , subq_10.ds__month + , subq_10.ds__quarter + , subq_10.ds__year + , subq_10.ds__extract_year + , subq_10.ds__extract_quarter + , subq_10.ds__extract_month + , subq_10.ds__extract_day + , subq_10.ds__extract_dow + , subq_10.ds__extract_doy + , subq_10.buy__ds__day + , subq_10.buy__ds__week + , subq_10.buy__ds__month + , subq_10.buy__ds__quarter + , subq_10.buy__ds__year + , subq_10.buy__ds__extract_year + , subq_10.buy__ds__extract_quarter + , subq_10.buy__ds__extract_month + , subq_10.buy__ds__extract_day + , subq_10.buy__ds__extract_dow + , subq_10.buy__ds__extract_doy + , subq_10.ds__day AS metric_time__day + , subq_10.ds__week AS metric_time__week + , subq_10.ds__month AS metric_time__month + , subq_10.ds__quarter AS metric_time__quarter + , subq_10.ds__year AS metric_time__year + , subq_10.ds__extract_year AS metric_time__extract_year + , subq_10.ds__extract_quarter AS metric_time__extract_quarter + , subq_10.ds__extract_month AS metric_time__extract_month + , subq_10.ds__extract_day AS metric_time__extract_day + , subq_10.ds__extract_dow AS metric_time__extract_dow + , subq_10.ds__extract_doy AS metric_time__extract_doy + , subq_10.user + , subq_10.session_id + , subq_10.buy__user + , subq_10.buy__session_id + , subq_10.buys + , subq_10.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_10 + ) subq_11 + ) subq_12 + ON + ( + subq_9.user = subq_12.user + ) AND ( + ( + subq_9.ds__day <= subq_12.ds__day + ) AND ( + subq_9.ds__day > DATE_ADD('day', -7, subq_12.ds__day) + ) + ) + ) subq_13 + ) subq_14 + ) subq_15 + ) subq_16 + GROUP BY + subq_16.metric_time__martian_day + ) subq_17 + ON + subq_5.metric_time__martian_day = subq_17.metric_time__martian_day + GROUP BY + COALESCE(subq_5.metric_time__martian_day, subq_17.metric_time__martian_day) +) subq_18 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity__plan0_optimized.sql new file mode 100644 index 0000000000..2093a9a50d --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity__plan0_optimized.sql @@ -0,0 +1,139 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE) / CAST(NULLIF(visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_24.visits) AS visits + , MAX(subq_36.buys) AS buys + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + subq_21.martian_day AS metric_time__martian_day + , SUM(subq_20.visits) AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_20 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_21 + ON + subq_20.metric_time__day = subq_21.ds + GROUP BY + subq_21.martian_day + ) subq_24 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_28.visits) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_28.metric_time__martian_day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_28.ds__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_28.metric_time__day) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_28.user) OVER ( + PARTITION BY + subq_31.user + , subq_31.ds__day + , subq_31.mf_internal_uuid + ORDER BY subq_28.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_31.mf_internal_uuid AS mf_internal_uuid + , subq_31.buys AS buys + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_26.martian_day AS metric_time__martian_day + , subq_25.ds__day AS ds__day + , subq_25.ds__day AS metric_time__day + , subq_25.user AS user + , subq_25.visits AS visits + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_25 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_26 + ON + subq_25.ds__day = subq_26.ds + ) subq_28 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , uuid() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_31 + ON + ( + subq_28.user = subq_31.user + ) AND ( + ( + subq_28.ds__day <= subq_31.ds__day + ) AND ( + subq_28.ds__day > DATE_ADD('day', -7, subq_31.ds__day) + ) + ) + ) subq_32 + GROUP BY + metric_time__martian_day + ) subq_36 + ON + subq_24.metric_time__martian_day = subq_36.metric_time__martian_day + GROUP BY + COALESCE(subq_24.metric_time__martian_day, subq_36.metric_time__martian_day) +) subq_37 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter__plan0.sql new file mode 100644 index 0000000000..afdefc4ccb --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter__plan0.sql @@ -0,0 +1,477 @@ +-- Compute Metrics via Expressions +SELECT + subq_20.metric_time__martian_day + , CAST(subq_20.buys AS DOUBLE) / CAST(NULLIF(subq_20.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_6.visits) AS visits + , MAX(subq_19.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + subq_5.metric_time__martian_day + , SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + SELECT + subq_4.metric_time__martian_day + , subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + GROUP BY + subq_5.metric_time__martian_day + ) subq_6 + FULL OUTER JOIN ( + -- Aggregate Measures + SELECT + subq_18.metric_time__martian_day + , SUM(subq_18.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_17.metric_time__martian_day + , subq_17.buys + FROM ( + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + SELECT + subq_16.metric_time__martian_day + , subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , uuid() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > DATE_ADD('day', -7, subq_14.ds__day) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 + GROUP BY + subq_18.metric_time__martian_day + ) subq_19 + ON + subq_6.metric_time__martian_day = subq_19.metric_time__martian_day + GROUP BY + COALESCE(subq_6.metric_time__martian_day, subq_19.metric_time__martian_day) +) subq_20 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql new file mode 100644 index 0000000000..a7b5e9da4f --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter__plan0_optimized.sql @@ -0,0 +1,156 @@ +-- Compute Metrics via Expressions +SELECT + metric_time__martian_day + , CAST(buys AS DOUBLE) / CAST(NULLIF(visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) AS metric_time__martian_day + , MAX(subq_27.visits) AS visits + , MAX(subq_40.buys) AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_22.visits AS visits + , subq_23.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_22 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_23 + ON + subq_22.metric_time__day = subq_23.ds + ) subq_24 + WHERE metric_time__martian_day = '2020-01-01' + GROUP BY + metric_time__martian_day + ) subq_27 + FULL OUTER JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Pass Only Elements: ['buys', 'metric_time__martian_day'] + -- Aggregate Measures + SELECT + metric_time__martian_day + , SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_32.visits) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_32.metric_time__martian_day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_32.ds__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_32.metric_time__day) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_32.user) OVER ( + PARTITION BY + subq_35.user + , subq_35.ds__day + , subq_35.mf_internal_uuid + ORDER BY subq_32.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_35.mf_internal_uuid AS mf_internal_uuid + , subq_35.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_30.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_28.ds__day AS ds__day + , subq_28.ds__day AS metric_time__day + , subq_28.user AS user + , subq_28.visits AS visits + , subq_29.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_28 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_29 + ON + subq_28.ds__day = subq_29.ds + ) subq_30 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_32 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , uuid() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_35 + ON + ( + subq_32.user = subq_35.user + ) AND ( + ( + subq_32.ds__day <= subq_35.ds__day + ) AND ( + subq_32.ds__day > DATE_ADD('day', -7, subq_35.ds__day) + ) + ) + ) subq_36 + GROUP BY + metric_time__martian_day + ) subq_40 + ON + subq_27.metric_time__martian_day = subq_40.metric_time__martian_day + GROUP BY + COALESCE(subq_27.metric_time__martian_day, subq_40.metric_time__martian_day) +) subq_41 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql new file mode 100644 index 0000000000..4b01dac7e6 --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0.sql @@ -0,0 +1,457 @@ +-- Compute Metrics via Expressions +SELECT + CAST(subq_19.buys AS DOUBLE) / CAST(NULLIF(subq_19.visits, 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Combine Aggregated Outputs + SELECT + MAX(subq_6.visits) AS visits + , MAX(subq_18.buys) AS buys + FROM ( + -- Aggregate Measures + SELECT + SUM(subq_5.visits) AS visits + FROM ( + -- Pass Only Elements: ['visits',] + SELECT + subq_4.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_3.metric_time__martian_day + , subq_3.metric_time__day + , subq_3.visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_1.metric_time__day AS metric_time__day + , subq_1.visits AS visits + , 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.visit__ds__day + , subq_0.visit__ds__week + , subq_0.visit__ds__month + , subq_0.visit__ds__quarter + , subq_0.visit__ds__year + , subq_0.visit__ds__extract_year + , subq_0.visit__ds__extract_quarter + , subq_0.visit__ds__extract_month + , subq_0.visit__ds__extract_day + , subq_0.visit__ds__extract_dow + , subq_0.visit__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.session + , subq_0.visit__user + , subq_0.visit__session + , subq_0.referrer_id + , subq_0.visit__referrer_id + , subq_0.visits + , subq_0.visitors + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_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 + CROSS JOIN ( + -- Aggregate Measures + SELECT + SUM(subq_17.buys) AS buys + FROM ( + -- Pass Only Elements: ['buys',] + SELECT + subq_16.buys + FROM ( + -- Find conversions for user within the range of 7 day + SELECT + subq_15.metric_time__martian_day + , subq_15.ds__day + , subq_15.metric_time__day + , subq_15.user + , subq_15.buys + , subq_15.visits + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_11.visits) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_11.metric_time__martian_day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_11.ds__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_11.metric_time__day) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_11.user) OVER ( + PARTITION BY + subq_14.user + , subq_14.ds__day + , subq_14.mf_internal_uuid + ORDER BY subq_11.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_14.mf_internal_uuid AS mf_internal_uuid + , subq_14.buys AS buys + FROM ( + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + subq_10.metric_time__martian_day + , subq_10.ds__day + , subq_10.metric_time__day + , subq_10.user + , subq_10.visits + FROM ( + -- Constrain Output with WHERE + SELECT + subq_9.metric_time__martian_day + , subq_9.ds__day + , subq_9.ds__week + , subq_9.ds__month + , subq_9.ds__quarter + , subq_9.ds__year + , subq_9.ds__extract_year + , subq_9.ds__extract_quarter + , subq_9.ds__extract_month + , subq_9.ds__extract_day + , subq_9.ds__extract_dow + , subq_9.ds__extract_doy + , subq_9.visit__ds__day + , subq_9.visit__ds__week + , subq_9.visit__ds__month + , subq_9.visit__ds__quarter + , subq_9.visit__ds__year + , subq_9.visit__ds__extract_year + , subq_9.visit__ds__extract_quarter + , subq_9.visit__ds__extract_month + , subq_9.visit__ds__extract_day + , subq_9.visit__ds__extract_dow + , subq_9.visit__ds__extract_doy + , subq_9.metric_time__day + , subq_9.metric_time__week + , subq_9.metric_time__month + , subq_9.metric_time__quarter + , subq_9.metric_time__year + , subq_9.metric_time__extract_year + , subq_9.metric_time__extract_quarter + , subq_9.metric_time__extract_month + , subq_9.metric_time__extract_day + , subq_9.metric_time__extract_dow + , subq_9.metric_time__extract_doy + , subq_9.user + , subq_9.session + , subq_9.visit__user + , subq_9.visit__session + , subq_9.referrer_id + , subq_9.visit__referrer_id + , subq_9.visits + , subq_9.visitors + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_7.ds__day AS ds__day + , subq_7.ds__week AS ds__week + , subq_7.ds__month AS ds__month + , subq_7.ds__quarter AS ds__quarter + , subq_7.ds__year AS ds__year + , subq_7.ds__extract_year AS ds__extract_year + , subq_7.ds__extract_quarter AS ds__extract_quarter + , subq_7.ds__extract_month AS ds__extract_month + , subq_7.ds__extract_day AS ds__extract_day + , subq_7.ds__extract_dow AS ds__extract_dow + , subq_7.ds__extract_doy AS ds__extract_doy + , subq_7.visit__ds__day AS visit__ds__day + , subq_7.visit__ds__week AS visit__ds__week + , subq_7.visit__ds__month AS visit__ds__month + , subq_7.visit__ds__quarter AS visit__ds__quarter + , subq_7.visit__ds__year AS visit__ds__year + , subq_7.visit__ds__extract_year AS visit__ds__extract_year + , subq_7.visit__ds__extract_quarter AS visit__ds__extract_quarter + , subq_7.visit__ds__extract_month AS visit__ds__extract_month + , subq_7.visit__ds__extract_day AS visit__ds__extract_day + , subq_7.visit__ds__extract_dow AS visit__ds__extract_dow + , subq_7.visit__ds__extract_doy AS visit__ds__extract_doy + , subq_7.ds__day AS metric_time__day + , subq_7.ds__week AS metric_time__week + , subq_7.ds__month AS metric_time__month + , subq_7.ds__quarter AS metric_time__quarter + , subq_7.ds__year AS metric_time__year + , subq_7.ds__extract_year AS metric_time__extract_year + , subq_7.ds__extract_quarter AS metric_time__extract_quarter + , subq_7.ds__extract_month AS metric_time__extract_month + , subq_7.ds__extract_day AS metric_time__extract_day + , subq_7.ds__extract_dow AS metric_time__extract_dow + , subq_7.ds__extract_doy AS metric_time__extract_doy + , subq_7.user AS user + , subq_7.session AS session + , subq_7.visit__user AS visit__user + , subq_7.visit__session AS visit__session + , subq_7.referrer_id AS referrer_id + , subq_7.visit__referrer_id AS visit__referrer_id + , subq_7.visits AS visits + , subq_7.visitors AS visitors + , subq_8.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , visits_source_src_28000.user_id AS visitors + , DATE_TRUNC('day', visits_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS ds__extract_doy + , visits_source_src_28000.referrer_id + , DATE_TRUNC('day', visits_source_src_28000.ds) AS visit__ds__day + , DATE_TRUNC('week', visits_source_src_28000.ds) AS visit__ds__week + , DATE_TRUNC('month', visits_source_src_28000.ds) AS visit__ds__month + , DATE_TRUNC('quarter', visits_source_src_28000.ds) AS visit__ds__quarter + , DATE_TRUNC('year', visits_source_src_28000.ds) AS visit__ds__year + , EXTRACT(year FROM visits_source_src_28000.ds) AS visit__ds__extract_year + , EXTRACT(quarter FROM visits_source_src_28000.ds) AS visit__ds__extract_quarter + , EXTRACT(month FROM visits_source_src_28000.ds) AS visit__ds__extract_month + , EXTRACT(day FROM visits_source_src_28000.ds) AS visit__ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM visits_source_src_28000.ds) AS visit__ds__extract_dow + , EXTRACT(doy FROM visits_source_src_28000.ds) AS visit__ds__extract_doy + , visits_source_src_28000.referrer_id AS visit__referrer_id + , visits_source_src_28000.user_id AS user + , visits_source_src_28000.session_id AS session + , visits_source_src_28000.user_id AS visit__user + , visits_source_src_28000.session_id AS visit__session + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_7 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_8 + ON + subq_7.ds__day = subq_8.ds + ) subq_9 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_10 + ) subq_11 + INNER JOIN ( + -- Add column with generated UUID + SELECT + subq_13.ds__day + , subq_13.ds__week + , subq_13.ds__month + , subq_13.ds__quarter + , subq_13.ds__year + , subq_13.ds__extract_year + , subq_13.ds__extract_quarter + , subq_13.ds__extract_month + , subq_13.ds__extract_day + , subq_13.ds__extract_dow + , subq_13.ds__extract_doy + , subq_13.buy__ds__day + , subq_13.buy__ds__week + , subq_13.buy__ds__month + , subq_13.buy__ds__quarter + , subq_13.buy__ds__year + , subq_13.buy__ds__extract_year + , subq_13.buy__ds__extract_quarter + , subq_13.buy__ds__extract_month + , subq_13.buy__ds__extract_day + , subq_13.buy__ds__extract_dow + , subq_13.buy__ds__extract_doy + , subq_13.metric_time__day + , subq_13.metric_time__week + , subq_13.metric_time__month + , subq_13.metric_time__quarter + , subq_13.metric_time__year + , subq_13.metric_time__extract_year + , subq_13.metric_time__extract_quarter + , subq_13.metric_time__extract_month + , subq_13.metric_time__extract_day + , subq_13.metric_time__extract_dow + , subq_13.metric_time__extract_doy + , subq_13.user + , subq_13.session_id + , subq_13.buy__user + , subq_13.buy__session_id + , subq_13.buys + , subq_13.buyers + , uuid() AS mf_internal_uuid + FROM ( + -- Metric Time Dimension 'ds' + SELECT + subq_12.ds__day + , subq_12.ds__week + , subq_12.ds__month + , subq_12.ds__quarter + , subq_12.ds__year + , subq_12.ds__extract_year + , subq_12.ds__extract_quarter + , subq_12.ds__extract_month + , subq_12.ds__extract_day + , subq_12.ds__extract_dow + , subq_12.ds__extract_doy + , subq_12.buy__ds__day + , subq_12.buy__ds__week + , subq_12.buy__ds__month + , subq_12.buy__ds__quarter + , subq_12.buy__ds__year + , subq_12.buy__ds__extract_year + , subq_12.buy__ds__extract_quarter + , subq_12.buy__ds__extract_month + , subq_12.buy__ds__extract_day + , subq_12.buy__ds__extract_dow + , subq_12.buy__ds__extract_doy + , subq_12.ds__day AS metric_time__day + , subq_12.ds__week AS metric_time__week + , subq_12.ds__month AS metric_time__month + , subq_12.ds__quarter AS metric_time__quarter + , subq_12.ds__year AS metric_time__year + , subq_12.ds__extract_year AS metric_time__extract_year + , subq_12.ds__extract_quarter AS metric_time__extract_quarter + , subq_12.ds__extract_month AS metric_time__extract_month + , subq_12.ds__extract_day AS metric_time__extract_day + , subq_12.ds__extract_dow AS metric_time__extract_dow + , subq_12.ds__extract_doy AS metric_time__extract_doy + , subq_12.user + , subq_12.session_id + , subq_12.buy__user + , subq_12.buy__session_id + , subq_12.buys + , subq_12.buyers + FROM ( + -- Read Elements From Semantic Model 'buys_source' + SELECT + 1 AS buys + , buys_source_src_28000.user_id AS buyers + , DATE_TRUNC('day', buys_source_src_28000.ds) AS ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM buys_source_src_28000.ds) AS ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS ds__extract_doy + , DATE_TRUNC('day', buys_source_src_28000.ds) AS buy__ds__day + , DATE_TRUNC('week', buys_source_src_28000.ds) AS buy__ds__week + , DATE_TRUNC('month', buys_source_src_28000.ds) AS buy__ds__month + , DATE_TRUNC('quarter', buys_source_src_28000.ds) AS buy__ds__quarter + , DATE_TRUNC('year', buys_source_src_28000.ds) AS buy__ds__year + , EXTRACT(year FROM buys_source_src_28000.ds) AS buy__ds__extract_year + , EXTRACT(quarter FROM buys_source_src_28000.ds) AS buy__ds__extract_quarter + , EXTRACT(month FROM buys_source_src_28000.ds) AS buy__ds__extract_month + , EXTRACT(day FROM buys_source_src_28000.ds) AS buy__ds__extract_day + , EXTRACT(DAY_OF_WEEK FROM buys_source_src_28000.ds) AS buy__ds__extract_dow + , EXTRACT(doy FROM buys_source_src_28000.ds) AS buy__ds__extract_doy + , buys_source_src_28000.user_id AS user + , buys_source_src_28000.session_id + , buys_source_src_28000.user_id AS buy__user + , buys_source_src_28000.session_id AS buy__session_id + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_12 + ) subq_13 + ) subq_14 + ON + ( + subq_11.user = subq_14.user + ) AND ( + ( + subq_11.ds__day <= subq_14.ds__day + ) AND ( + subq_11.ds__day > DATE_ADD('day', -7, subq_14.ds__day) + ) + ) + ) subq_15 + ) subq_16 + ) subq_17 + ) subq_18 +) subq_19 diff --git a/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql new file mode 100644 index 0000000000..e4bbcd6a4c --- /dev/null +++ b/tests_metricflow/snapshots/test_custom_granularity.py/SqlQueryPlan/Trino/test_conversion_metric_with_custom_granularity_filter_not_in_group_by__plan0_optimized.sql @@ -0,0 +1,138 @@ +-- Combine Aggregated Outputs +-- Compute Metrics via Expressions +SELECT + CAST(MAX(subq_38.buys) AS DOUBLE) / CAST(NULLIF(MAX(subq_26.visits), 0) AS DOUBLE) AS visit_buy_conversion_rate_7days +FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits',] + -- Aggregate Measures + SELECT + SUM(visits) AS visits + FROM ( + -- Pass Only Elements: ['visits', 'metric_time__day'] + -- Join to Custom Granularity Dataset + SELECT + subq_21.visits AS visits + , subq_22.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + -- Metric Time Dimension 'ds' + SELECT + DATE_TRUNC('day', ds) AS metric_time__day + , 1 AS visits + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_21 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_22 + ON + subq_21.metric_time__day = subq_22.ds + ) subq_23 + WHERE metric_time__martian_day = '2020-01-01' +) subq_26 +CROSS JOIN ( + -- Find conversions for user within the range of 7 day + -- Pass Only Elements: ['buys',] + -- Aggregate Measures + SELECT + SUM(buys) AS buys + FROM ( + -- Dedupe the fanout with mf_internal_uuid in the conversion data set + SELECT DISTINCT + FIRST_VALUE(subq_31.visits) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS visits + , FIRST_VALUE(subq_31.metric_time__martian_day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__martian_day + , FIRST_VALUE(subq_31.ds__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS ds__day + , FIRST_VALUE(subq_31.metric_time__day) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS metric_time__day + , FIRST_VALUE(subq_31.user) OVER ( + PARTITION BY + subq_34.user + , subq_34.ds__day + , subq_34.mf_internal_uuid + ORDER BY subq_31.ds__day DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS user + , subq_34.mf_internal_uuid AS mf_internal_uuid + , subq_34.buys AS buys + FROM ( + -- Constrain Output with WHERE + -- Pass Only Elements: ['visits', 'ds__day', 'metric_time__day', 'metric_time__martian_day', 'user'] + SELECT + metric_time__martian_day + , ds__day + , metric_time__day + , subq_29.user + , visits + FROM ( + -- Metric Time Dimension 'ds' + -- Join to Custom Granularity Dataset + SELECT + subq_27.ds__day AS ds__day + , subq_27.ds__day AS metric_time__day + , subq_27.user AS user + , subq_27.visits AS visits + , subq_28.martian_day AS metric_time__martian_day + FROM ( + -- Read Elements From Semantic Model 'visits_source' + SELECT + 1 AS visits + , DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + FROM ***************************.fct_visits visits_source_src_28000 + ) subq_27 + LEFT OUTER JOIN + ***************************.mf_time_spine subq_28 + ON + subq_27.ds__day = subq_28.ds + ) subq_29 + WHERE metric_time__martian_day = '2020-01-01' + ) subq_31 + INNER JOIN ( + -- Read Elements From Semantic Model 'buys_source' + -- Metric Time Dimension 'ds' + -- Add column with generated UUID + SELECT + DATE_TRUNC('day', ds) AS ds__day + , user_id AS user + , 1 AS buys + , uuid() AS mf_internal_uuid + FROM ***************************.fct_buys buys_source_src_28000 + ) subq_34 + ON + ( + subq_31.user = subq_34.user + ) AND ( + ( + subq_31.ds__day <= subq_34.ds__day + ) AND ( + subq_31.ds__day > DATE_ADD('day', -7, subq_34.ds__day) + ) + ) + ) subq_35 +) subq_38