def _split_where_expression_and_having_expression(expression: BinaryExpression) -> Tuple[(Optional[BinaryExpression], Optional[BinaryExpression])]:
    stack = [expression]
    and_expressions = []
    while stack:
        exp = stack.pop()
        if (exp is None):
            continue
        if (exp.operator == 'AND'):
            stack.append(exp.right)
            stack.append(exp.left)
            continue
        and_expressions.append(exp)
    where_expressions = []
    having_expressions = []
    for exp in and_expressions:
        if _check_aggregation(exp):
            having_expressions.append(exp)
        else:
            where_expressions.append(exp)
    where_expression = None
    having_expression = None
    if where_expressions:
        where_expression = reduce(operator.and_, where_expressions)
    if having_expressions:
        having_expression = reduce(operator.and_, having_expressions)
    return (where_expression, having_expression)
def _split_where_expression_and_having_expression(expression: BinaryExpression) -> Tuple[(Optional[BinaryExpression], Optional[BinaryExpression])]:
    stack = [expression]
    and_expressions = []
    while stack:
        exp = stack.pop()
        if (exp is None):
            continue
        if (exp.operator == 'AND'):
            stack.append(exp.right)
            stack.append(exp.left)
            continue
        and_expressions.append(exp)
    where_expressions = []
    having_expressions = []
    for exp in and_expressions:
        if _check_aggregation(exp):
            having_expressions.append(exp)
        else:
            where_expressions.append(exp)
    where_expression = None
    having_expression = None
    if where_expressions:
        where_expression = reduce(operator.and_, where_expressions)
    if having_expressions:
        having_expression = reduce(operator.and_, having_expressions)
    return (where_expression, having_expression)