Some aggregate functions are commutative with some arithmetic expressions.

```
avg(x + const) = avg(x) + const
```

This is applicable for aggregate functions: `sum`, `avg`, `min`, `max` and operations: `+`, `-`, `*`, `/` (but not for `intDiv` and `modulo`).

In case of integer overflow it either works correctly (for `sum`) or we may assume that integer overflow is implementation specific behaviour and apply optimization under this assumption.

**Possible implementation**

AST rewrite with InDepthNodeVisitor.
Should not rewrite if expression has alias.
{
    switch (value.getType())
    {
        case Field::Types::UInt64: return UInt64(0);
        case Field::Types::Int64: return Int64(0);
        case Field::Types::Float64: return Float64(0);
        case Field::Types::UInt128: return UInt128(0);
        case Field::Types::Int128: return Int128(0);
        default:
            break;
    }
    throw Exception("Unexpected literal type in function", ErrorCodes::BAD_TYPE_OF_FIELD);
}
const String & changeNameIfNeeded(const String & func_name, const String & child_name, const ASTLiteral & literal)
{
    static const std::unordered_map<String, std::unordered_set<String>> matches = {
        { "min", { "multiply", "divide" } },
        { "max", { "multiply", "divide" } }
    };
    static const std::unordered_map<String, String> swap_to = {
        { "min", "max" },
        { "max", "min" }
    };
    if (literal.value < zeroField(literal.value) && matches.count(func_name) && matches.find(func_name)->second.count(child_name))
        return swap_to.find(func_name)->second;
    return func_name;
}
ASTPtr tryExchangeFunctions(const ASTFunction & func)