class_docstr: Visits the SQL query plan to simplify sub-queries. On each visit, return a simplified node.
  
  Unlike SqlSubQueryReducerVisitor, this will re-write expressions to realize more reductions.
docstr: Returns true if the given node can be reduced with the parent node.
  
  Reducing this node means eliminating the SELECT of this node and merging it with the parent SELECT. This
  checks for the cases where we are able to reduce.
code: def _current_node_can_be_reduced(
      self, node: SqlSelectStatementNode
  ) -> bool:  # noqa: D
      """Returns true if the given node can be reduced with the parent node.
  
      Reducing this node means eliminating the SELECT of this node and merging it with the parent SELECT. This
      checks for the cases where we are able to reduce.
      """
      # If this node has multiple parents (i.e. a join) that are complex, then this can't be collapsed.
      is_join = len(node.join_descs) > 0
      has_multiple_parent_nodes = len(node.parent_nodes) > 1
      if has_multiple_parent_nodes or is_join:
          return False
  
      assert len(node.parent_nodes) == 1
      parent_node = node.parent_nodes[0]
  
      # If the parent node is not a SELECT statement, then this can't be collapsed. e.g. with a table as a parent like
      # SELECT foo FROM bar
      if not parent_node.as_select_node:
          return False
      parent_select_node = parent_node.as_select_node
  
      # More conditions where we don't want to collapse. It's not impossible with these cases, but not reducing in
      # these cases for simplicity.
  
      # Re-writing string expressions / column alias expressions not yet supported, so don't reduce in those cases.
      if SqlRewritingSubQueryReducerVisitor._statement_contains_difficult_expressions(
          node
      ):
          return False
  
      # Don't reduce distinct selects
      if parent_select_node.distinct:
          return False
  
      # Skip this case for simplicity of reasoning.
      if (
          len(node.order_bys) > 0
          and len(parent_select_node.order_bys) > 0
      ):
          return False
  
      # Skip this case for simplicity of reasoning.
      if (
          len(parent_select_node.group_bys) > 0
          and len(node.group_bys) > 0
      ):
          return False
  
      # TODO: Check for the following case:
      # SELECT
      #   bookings
      #   , 2 * bookings AS twice_bookings
      # FROM (
      #   SELECT,
      #     SUM(bookings) AS bookings
      #     , fct_bookings_src.is_instant
      #   FROM (
      #     SELECT * FROM demo.fct_bookings
      #   ) fct_bookings_src
      #   GROUP BY fct_bookings_src.is_instant
      # ) src
      #
      # If this is reduced, then the GROUP BY will refer to an unused column.
  
      # Don't reduce if the ORDER BYs aren't column reference expressions for simplicity.
      for order_by in node.order_bys:
          order_by_column_reference_expression = (
              order_by.expr.as_column_reference_expression
          )
          if not order_by_column_reference_expression:
              return False
          # Also for simplicity, the ORDER BY must match one of the SELECT expressions.
          if not SqlRewritingSubQueryReducerVisitor._find_matching_select_column(
              col_ref=order_by_column_reference_expression.col_ref,
              select_columns=node.select_columns,
          ):
              return False
  
      # If the parent has a GROUP BY and this has a WHERE, avoid reducing as the WHERE could reference an
      # aggregation expression.
      if len(parent_select_node.group_bys) > 0 and node.where:
          return False
  
      # If the parent has a GROUP BY, the case where it's easiest to merge this with the parent is if all select
      # columns are column references.
      if len(
          parent_select_node.group_bys
      ) > 0 and not SqlRewritingSubQueryReducerVisitor._select_columns_are_column_references(
          node.select_columns
      ):
          return False
  
      # If the parent select node contains string columns, and this has a GROUP BY, don't reduce as string columns
      # can have special meanings in a GROUP BY. For example,
      #
      # SELECT
      #   a.col1 AS col1
      #   , a.col2 AS col2
      # FROM (
      #   SELECT
      #     b.col1 AS col1
      #     , 1 AS col2
      #   FROM foo b
      # ) a
      # GROUP BY a.col2
      #
      # would be rewritten in the current algorithm to
      #
      # SELECT
      #   b.col1 AS col1
      #   , 1 AS col2
      # FROM foo b
      # GROUP by 1
      #
      # However, the GROUP BY would be wrong as the "1" string expression would be interpreted as selecting the 1st
      # item in the SELECT to group by.
  
      if len(
          node.group_bys
      ) > 0 and SqlRewritingSubQueryReducerVisitor._select_columns_contain_string_expressions(
          select_columns=parent_select_node.select_columns,
      ):
          return False
  
      return True
  
imports: from __future__ import annotations
  import logging
  from dataclasses import dataclass
  from typing import List, Optional, Sequence, Tuple
  from metricflow.sql.optimizer.sql_query_plan_optimizer import SqlQueryPlanOptimizer
  from metricflow.sql.sql_exprs import SqlColumnAliasReferenceExpression, SqlColumnReference, SqlColumnReplacements, SqlExpressionNode, SqlExpressionTreeLineage, SqlLogicalExpression, SqlLogicalOperator
  from metricflow.sql.sql_plan import SqlJoinDescription, SqlOrderByDescription, SqlQueryPlanNode, SqlQueryPlanNodeVisitor, SqlSelectColumn, SqlSelectQueryFromClauseNode, SqlSelectStatementNode, SqlTableFromClauseNode
label_desc: Use image node_id 7 for calling the SqlRewritingSubQueryReducerVisitor obj's underlying member method code with example usage: obj._current_node_can_be_reduced(node) and returns: True, False, False, False, False, False, False, False, False, False, False, False