class_docstr: Helper class for constructing various join components in a SqlQueryPlan.
docstr: Creates the sql join description for combining two separate output datasets.
  
  These might be combined in service of producing complete output for end user consumption, in which
  case the join type will be FULL OUTER in order to ensure all rows are included. In this case, the
  join must account for all past table aliases seen in prior joins in order to produce the final
  coalesce expression for processing the join correctly.
  
  Metric data sets might also be combined to serve as inputs to a derived metric, in which case the
  join type will not be a FULL OUTER, and we should use null-safe column equality comparisons with
  the relevant join type for
docstr_tok: ["Creates","the","sql","join","description","for","combining","two","separate","output","datasets",".","These","might","be","combined","in","service","of","producing","complete","output","for","end","user","consumption",",","in","which","case","the","join","type","will","be","FULL","OUTER","in","order","to","ensure","all","rows","are","included",".","In","this","case",",","the","join","must","account","for","all","past","table","aliases","seen","in","prior","joins","in","order","to","produce","the","final","coalesce","expression","for","processing","the","join","correctly",".","Metric","data","sets","might","also","be","combined","to","serve","as","inputs","to","a","derived","metric",",","in","which","case","the","join","type","will","not","be","a","FULL","OUTER",",","and","we","should","use","null-safe","column","equality","comparisons","with","the","relevant","join","type","for"]
code: def make_join_description_for_combining_datasets(
      from_data_set: AnnotatedSqlDataSet,
      join_data_set: AnnotatedSqlDataSet,
      join_type: SqlJoinType,
      column_names: Sequence[str],
      table_aliases_for_coalesce: Sequence[str],
  ) -> SqlJoinDescription:
      """Creates the sql join description for combining two separate output datasets.
  
      These might be combined in service of producing complete output for end user consumption, in which
      case the join type will be FULL OUTER in order to ensure all rows are included. In this case, the
      join must account for all past table aliases seen in prior joins in order to produce the final
      coalesce expression for processing the join correctly.
  
      Metric data sets might also be combined to serve as inputs to a derived metric, in which case the
      join type will not be a FULL OUTER, and we should use null-safe column equality comparisons with
      the relevant join type for
      """
      if join_type is SqlJoinType.FULL_OUTER:
          assert (
              len(column_names) > 0
          ), "Attempting to do a FULL OUTER JOIN to combine metrics, but no columns were provided for join keys!"
          equality_exprs = [
              SqlQueryPlanJoinBuilder._make_equality_expression_for_full_outer_join(
                  table_aliases_for_coalesce,
                  join_data_set.alias,
                  colname,
              )
              for colname in column_names
          ]
          on_condition = (
              SqlLogicalExpression(
                  operator=SqlLogicalOperator.AND,
                  args=tuple(equality_exprs),
              )
              if len(equality_exprs) > 1
              else equality_exprs[0]
          )
          return SqlJoinDescription(
              right_source=join_data_set.data_set.sql_select_node,
              right_source_alias=join_data_set.alias,
              on_condition=on_condition,
              join_type=join_type,
          )
      else:
          column_equality_descriptions = [
              ColumnEqualityDescription(
                  left_column_alias=name,
                  right_column_alias=name,
                  treat_nulls_as_equal=True,
              )
              for name in column_names
          ]
          return SqlQueryPlanJoinBuilder.make_column_equality_sql_join_description(
              right_source_node=join_data_set.data_set.sql_select_node,
              left_source_alias=from_data_set.alias,
              right_source_alias=join_data_set.alias,
              column_equality_descriptions=column_equality_descriptions,
              join_type=join_type,
          )
  
imports: from __future__ import annotations
  from dataclasses import dataclass
  from typing import List, Optional, Sequence, Tuple
  from dbt_semantic_interfaces.protocols.metric import MetricTimeWindow
  from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity
  from metricflow.assert_one_arg import assert_exactly_one_arg_set
  from metricflow.dataflow.dataflow_plan import JoinConversionEventsNode, JoinDescription, JoinOverTimeRangeNode, JoinToTimeSpineNode
  from metricflow.dataset.sql_dataset import SqlDataSet
  from metricflow.plan_conversion.sql_expression_builders import make_coalesced_expr
  from metricflow.sql.sql_exprs import SqlColumnReference, SqlColumnReferenceExpression, SqlComparison, SqlComparisonExpression, SqlDateTruncExpression, SqlIsNullExpression, SqlLogicalExpression, SqlLogicalOperator, SqlSubtractTimeIntervalExpression
  from metricflow.sql.sql_plan import SqlExpressionNode, SqlJoinDescription, SqlJoinType, SqlSelectStatementNode
label_desc: Use image node_id 5 for calling the SqlQueryPlanJoinBuilder obj's underlying member method code with example usage: obj.make_join_description_for_combining_datasets(from_data_set, join_data_set, join_type, column_names, table_aliases_for_coalesce) and returns: SqlJoinDescription, SqlQueryPlanJoinBuilder