**Use case**

Comparison between DateTime64 and DateTime / Date types is allowed but the behavior is confusing (it looks like used numerical comparison):

* from one side for zero-precision it works as expected (values compared as datetime-based ones): 

```sql
SELECT toTypeName(dt64) AS dt64_typename, dt64 = dt
FROM 
(
    SELECT 
        toDateTime64(toStartOfInterval(now(), toIntervalSecond(1), 'UTC'), 0, 'UTC') AS dt64,
        toStartOfInterval(now(), toIntervalSecond(1), 'UTC') AS dt
)

/*
┌─dt64_typename────────┬─equals(dt64, dt)─┐
│ DateTime64(0, 'UTC') │                1 │
└──────────────────────┴──────────────────┘
*/
```
* from another side for non-zero-precision its behavior is unexpected if not used explicit type conversion:

```sql
SELECT 
    toTypeName(dt64) AS dt64_typename,
    dt64 = dt,
    toDateTime(dt64) = dt,
    dt64 = toDateTime64(dt, 1, 'UTC')
FROM 
(
    SELECT 
        toDateTime64(toStartOfInterval(now(), toIntervalSecond(1), 'UTC'), 1, 'UTC') AS dt64,
        toStartOfInterval(now(), toIntervalSecond(1), 'UTC') AS dt
)
/*
┌─dt64_typename────────┬─equals(dt64, dt)─┬─equals(toDateTime(dt64), dt)─┬─equals(dt64, toDateTime64(dt, 1, 'UTC'))─┐
│ DateTime64(1, 'UTC') │                0 │                            1 │                                        1 │
└──────────────────────┴──────────────────┴──────────────────────────────┴──────────────────────────────────────────┘
*/
```

**Describe the solution you'd like**
I think this comparison either:
- should be not allowed and throw an exception to ask for user uses explicit conversion
- or make valid implicit conversion relying on datetime/date essence of values

else
            {
                auto impl_tail = func_compare_tail->build(tmp_columns);
                less_columns[i].type = impl_tail->getResultType();
                less_columns[i].column = impl_tail->execute(tmp_columns, less_columns[i].type, input_rows_count);
            }
        }
        
        
        
        
        
        
        size_t i = tuple_size - 1;
        tmp_columns[0] = less_columns[i];
        while (i > 0)
        {
            --i;
            tmp_columns[1] = equal_columns[i];
            auto func_and_adaptor = func_and->build(tmp_columns);
            tmp_columns[0].column = func_and_adaptor->execute(tmp_columns, func_and_adaptor->getResultType(), input_rows_count);
            tmp_columns[0].type = func_and_adaptor->getResultType();
            tmp_columns[1] = less_columns[i];
            auto func_or_adaptor = func_or->build(tmp_columns);
            tmp_columns[0].column = func_or_adaptor->execute(tmp_columns, func_or_adaptor->getResultType(), input_rows_count);
            tmp_columns[tmp_columns.size() - 1].type = func_or_adaptor->getResultType();
        }
        return tmp_columns[0].column;
    }
    ColumnPtr executeGenericIdenticalTypes(const IColumn * c0, const IColumn * c1) const