@@ -391,6 +391,26 @@ static void BuildUpdateSemantics(DeltaViewModel &model, const PlanAnalysis &anal
391391 }
392392}
393393
394+ static bool IsTransparentDistinctWrapper (LogicalOperatorType type) {
395+ return type == LogicalOperatorType::LOGICAL_CREATE_TABLE || type == LogicalOperatorType::LOGICAL_FILTER ||
396+ type == LogicalOperatorType::LOGICAL_ORDER_BY || type == LogicalOperatorType::LOGICAL_LIMIT ||
397+ type == LogicalOperatorType::LOGICAL_TOP_N ;
398+ }
399+
400+ static bool HasOuterProjectionOverDistinct (const CreateMVPlanFacts &facts) {
401+ auto *node = facts.root ;
402+ bool found_projection = false ;
403+ while (node && node->children .size () == 1 ) {
404+ if (node->type == LogicalOperatorType::LOGICAL_PROJECTION ) {
405+ found_projection = true ;
406+ } else if (!IsTransparentDistinctWrapper (node->type )) {
407+ break ;
408+ }
409+ node = node->children [0 ].get ();
410+ }
411+ return found_projection && node && node->type == LogicalOperatorType::LOGICAL_DISTINCT ;
412+ }
413+
394414static void BuildGroupColumns (DeltaViewModel &model, const CreateMVPlanFacts &facts, const vector<string> &output_names,
395415 idx_t visible_output_count) {
396416 const auto &analysis = facts.analysis ;
@@ -411,9 +431,14 @@ static void BuildGroupColumns(DeltaViewModel &model, const CreateMVPlanFacts &fa
411431 model.group_columns .size ());
412432 }
413433 } else if (model.distinct_at_top ) {
414- model.group_columns = analysis.aggregate_columns ;
415- } else if (analysis.found_distinct && analysis.aggregate_columns .empty ()) {
416- model.group_columns = analysis.aggregate_columns ;
434+ AddVisibleGroupNames (model.group_columns , output_names);
435+ } else if (analysis.found_distinct && !analysis.found_aggregation && HasOuterProjectionOverDistinct (facts)) {
436+ AddVisibleGroupNames (model.group_columns , output_names);
437+ if (!model.group_columns .empty ()) {
438+ AddUnique (model.strategy_reasons , DeltaStrategyReason::INNER_DISTINCT_PROJECTION_RECOMPUTE );
439+ OPENIVM_DEBUG_PRINT (" [CREATE MV] Inner DISTINCT below an outer projection -- using "
440+ " GROUP_RECOMPUTE\n " );
441+ }
417442 } else if (group_count > 0 && group_index != DConstants::INVALID_INDEX ) {
418443 model.group_columns = DeriveGroupColumnNames (facts, group_index, group_count, output_names);
419444 }
@@ -666,6 +691,8 @@ const char *DeltaStrategyReasonName(DeltaStrategyReason reason) {
666691 return " OUTER_JOIN_AGGREGATE_RECOMPUTE" ;
667692 case DeltaStrategyReason::OUTER_JOIN_PRESERVED_TABLE_FUNCTION_RECOMPUTE :
668693 return " OUTER_JOIN_PRESERVED_TABLE_FUNCTION_RECOMPUTE" ;
694+ case DeltaStrategyReason::INNER_DISTINCT_PROJECTION_RECOMPUTE :
695+ return " INNER_DISTINCT_PROJECTION_RECOMPUTE" ;
669696 default :
670697 return " UNKNOWN" ;
671698 }
@@ -861,11 +888,10 @@ bool IsDistinctAtTop(const CreateMVPlanFacts &facts, const vector<string> &outpu
861888 }
862889
863890 auto *node = facts.root ;
864- while (node && node->children .size () == 1 &&
865- (node->type == LogicalOperatorType::LOGICAL_CREATE_TABLE ||
866- node->type == LogicalOperatorType::LOGICAL_PROJECTION ||
867- node->type == LogicalOperatorType::LOGICAL_FILTER || node->type == LogicalOperatorType::LOGICAL_ORDER_BY ||
868- node->type == LogicalOperatorType::LOGICAL_LIMIT || node->type == LogicalOperatorType::LOGICAL_TOP_N )) {
891+ while (node && node->children .size () == 1 ) {
892+ if (!IsTransparentDistinctWrapper (node->type )) {
893+ break ;
894+ }
869895 node = node->children [0 ].get ();
870896 }
871897 if (node && node->type == LogicalOperatorType::LOGICAL_DISTINCT ) {
0 commit comments