In default mode, the default data type cannot be empty. But ANSI standards require it to be nullable.
| ||
|Query example |
|SQL ||SELECT value, changed FROM system.settings WHERE name LIKE '%dialect_type%'; || |\
| \ | ||
| Output in default mode: | \ | |
| 0, 0 | Output in ANSI mode: | \ |
| 1, 1 |
The Time data type has been added.
Time data types with timezone support are part of the ANSI SQL standard and are supported by MySQL and PostgreSQL. The format of the Time data type is hh:mm:ss[.nnnnnnn]. Internally represented as Int64. Its precision uses scale as a parameter. The maximum value of scale is 9, which equals the number of digits after the decimal point; the default value is 3.
Example: Functions using the Time data type.
select toHour('11:20:30'::Time); select Hour('11:20:30'::Time); select toMinute('11:20:30'::Time); select Minute('11:20:30'::Time); select toSecond('11:20:30'::Time); select Second('11:20:30'::Time); select addYears('11:20:30'::Time(3), 5); select addYears('11:20:30'::Time(4), 20); select subtractYears('11:20:30'::Time(5), 5); select subtractYears('11:20:30'::Time(6), 20); select addMonths('11:20:30'::Time(3), 5); select addMonths('11:20:30'::Time(4), 20); select subtractMonths('11:20:30'::Time(5), 5); select subtractMonths('11:20:30'::Time(6), 20); select addDays('11:20:30'::Time(3), 5); select addDays('11:20:30'::Time(4), 20); select subtractDays('11:20:30'::Time(5), 5); select subtractDays('11:20:30'::Time(6), 20); select addHours('11:20:30'::Time(3), 5); select addHours('11:20:30'::Time(4), 20); select subtractHours('11:20:30'::Time(5), 5); select subtractHours('11:20:30'::Time(6), 20); select addMinutes('11:20:30'::Time(2), 50); select addMinutes('11:20:30'::Time(3), 2000); select subtractMinutes('11:20:30'::Time, 50); select subtractMinutes('11:20:30'::Time(1), 5000); select addSeconds('11:20:30'::Time, 500); select addSeconds('11:20:30'::Time(2), 200000); select subtractSeconds('11:20:30'::Time, 500); select subtractSeconds('11:20:30'::Time(1), 500000);
The supported data range for DateTime64 type is: [1900-01-01 00:00:00, 2299-12-31 23:59:59.99999999].
In ClickHouse mode, implicit type conversion cannot occur between some numerical value types if the conversion would result in precision loss (such as Decimal & Float, Int64 & Float) or performance degradation (such as UInt64 & Ints). In ANSI mode, this type of implicit conversion is allowed.
Related sub-options: allow_extended_type_conversion: 0 / 1
| ||
|Query example 1: Implicit conversion between Decimal and Float |
|SQL ||SELECT 1::Decimal32(2) UNION ALL SELECT 1::Float64 || |\
| \ | ||
| Output in ClickHouse mode: | \ | |
| DB::Exception: There is no supertype for types Decimal(9, 2), Float64 because some of them have no lossless conversion to Decimal | Output in ANSI mode: | \ |
| 1 | \ | |
| 1 |
| ||
|Query example 2: Implicit conversion between Int64 and Float |
|SQL ||SELECT 1::Int64 UNION ALL SELECT 1::Float64 || |\
| \ | ||
| Output in ClickHouse mode: | \ | |
| DB::Exception: There is no supertype for types Int64, Float64 because some of them are integers and some are floating point, but there is no floating point type, that can exactly represent all required integers | Output in ANSI mode: | \ |
| 1 | \ | |
| 1 |
| ||
|Query example 3: Implicit conversion between UInt64 and Int |
|SQL ||SELECT 1::UInt64 UNION ALL SELECT 1::Int32 || |\
| \ | ||
| Output in ClickHouse mode: | \ | |
| DB::Exception: There is no supertype for types UInt64, Int32 because some of them are signed integers and some are unsigned integers, but there is no signed integer type, that can exactly represent all required unsigned integer values | Output in ANSI mode: | \ |
| 1 | \ | |
| 1 |
By default, numeric literals with a decimal point are parsed as floating-point types. In ANSI mode, literals are parsed as Decimal fixed-point data types to ensure precision.
| ||
|Query example: |
|SQL ||SELECT toTypeName(1.1); || |\
| \ | ||
| Output in default mode: Float64 | Output in ANSI mode: Decimal(18, 1) |
When there are duplicate alias and table fields, in CLICKHOUSE Mode, alias is given parsing priority; in ANSI Mode, the table field is given parsing priority. This rule does not apply to the ORDER BY clause.
Related sub-options: prefer_column_name_to_alias: 0 / 1
| ||
|Example Query 1: |
|SQL ||SELECT a + 1 AS a ||FROM || (SELECT 1 AS a) ||WHERE a > 1 ORDER BY a; || |\
| \ | ||
| ClickHouse Mode output: | \ | |
| 2 | ANSI mode output: | \ |
| Empty set |
| ||
|Example Query 2: The prefer column name to alias rule does not apply to the ORDER BY clause; in both modes, a is parsed as alias |
|SQL ||SELECT a AS origin_a, -a AS a ||FROM || (SELECT 1 AS a UNION ALL SELECT 2) ||ORDER BY a ASC; || |\
| \ | ||
| ClickHouse Mode output: | \ | |
| 2, -2 | \ | |
| 1, -1 | ANSI mode output: | \ |
| 2, -2 | \ | |
| 1, -1 |
In ClickHouse Mode, when joining two tables with duplicate fields, referencing that name is interpreted as referencing the field from the first table. This behavior is inconsistent with mainstream databases, and the semantics become even more ambiguous in multi-table joins. In ANSI Mode, referencing ambiguous names is prohibited.
| ||
|Example Query: |
|SQL ||SELECT a ||FROM || (SELECT 1 AS a) x || CROSS JOIN || (SELECT 's' AS a) y; || |\
| \ | ||
| ClickHouse Mode output: | \ | |
| 1 | ANSI mode output: | \ |
| DB::Exception: Identifier a is ambiguous. |
In ANSI Mode, if the parameter of the CAST function is of nullable type, the result type remains nullable.
Related sub-options: cast_keep_nullable
| ||
|Example Query |
|SQL ||SELECT toTypeName(CAST(1::Int32 AS Int64)), toTypeName(CAST(1::Nullable(Int32) AS Int64)); || |\
| \ | ||
| Default Mode output: | \ | |
| Int64, Int64 | ANSI mode output: | \ |
| Int64, Nullable(Int64) |
In Default Mode, the decimal places of the result type for decimal division are: S = S1. When S1 is not large enough, this can cause significant rounding errors. In ANSI Mode, the scale value is: S = max (6, S1).
Related sub-options: decimal_division_use_extended_scale
| ||
|Example Query |
|SQL ||SELECT 2.0::Decimal64(1) / 3, toTypeName(2.0::Decimal64(1) / 3); || |\
| \ | ||
| Default Mode output: | \ | |
| 0.6, Decimal(18, 1) | ANSI mode output: | \ |
| 0.666666, Decimal(18, 6) |
Some decimal scenarios are prone to overflow errors due to rescaling. In ANSI Mode, the underlying storage type is automatically promoted to minimize overflow. These scenarios include:
Related sub-options: decimal_arithmetic_promote_storage
| ||
|Example Query |
|SQL ||SELECT 2.0::Decimal32(4) * 3.0::Decimal32(5); || |\
| \ | ||
| Default Mode output: | \ | |
| DB::Exception: Decimal math overflow | ANSI mode output: | \ |
| 6.000000000 |
In ANSI Mode, regardless of the frame type, all rows with the same value in the ORDER BY expression are treated as the same row.
| ||
|Example Query |
|SQL ||WITH nums AS (SELECT arrayJoin([1, 2, 1, 1]) as src) SELECT percent_rank() OVER (ORDER BY src ROWS CURRENT ROW) from nums || |\
| \ | ||
| Default Mode output: | \ | |
| 0 | \ | |
| 0.3333333333333333 | \ | |
| 0.6666666666666666 | \ | |
| 1 | ANSI mode output: | \ |
| 0 | \ | |
| 0 | \ | |
| 0 | \ | |
| 1 |
In ANSI mode, just like the regular = operator, comparing two values results in 0 (not equal) or 1 (equal). In other words: 'a' <=> 'b' produces 0, 'a' <=> 'a' produces 1.
Unlike the regular = operator, NULL values have no special meaning, so it never produces NULL as a result. Therefore: 'a'<=>NULL produces 0, NULL<=>NULL produces 1.
| ||
|Example: |
|SQL ||SELECT NULL<=>NULL; ||SELECT NULL<=>0; ||SELECT 0 IS DISTINCT FROM NULL; ||SELECT 0 IS NOT DISTINCT FROM NULL; ||SELECT ''; || |\
| \ | ||
| ANSI mode output: | \ | |
| 1 | \ | |
| 0 | \ | |
| 1 | \ | |
| 0 |
ANSI mode supports correlated subqueries.
Example:
INSERT INTO orders(order_id, customer_id, amount) VALUES (1, 101, 100), (2, 101, 120), (3, 102, 30); SELECT order_id FROM customers x WHERE amount = (SELECT avg(amount)FROM customers yWHERE x.customer_id = y.customer_id)
In default mode, for cases where there is no join record, the outer join defaults to 0 or "". In ANSI mode, the default value is NULL.
Related suboption: join_use_nulls
| ||
|Example: |
|SQL ||SELECT a, b FROM (SELECT 1 AS k, 100 AS a) x LEFT JOIN (SELECT 2 AS k, 200 AS b) y ON x.k = y.k; || |\
| \ | ||
| Default mode output: | \ | |
| 100, 0 | ANSI mode output: | \ |
| 100, NULL |
In default mode, you can specify conditions for the outer join. In ANSI mode, specifying conditions for the outer join is not allowed.
| ||
|Example 1: When using a left join, the output of the join key is the data from the left table |
|SQL ||SELECT k FROM (SELECT 1 as k) LEFT JOIN (SELECT 2 as k) USING k; || |\
| \ | ||
| Default mode output: | \ | |
| 1 | ANSI mode output: | \ |
| Syntax error: failed at position 57; |
| ||
|Example 2: When using a right join, the output of the join key is the data from the right table |
|SQL ||SELECT k FROM (SELECT 1 as k) RIGHT JOIN (SELECT 2 as k) USING k; || |\
| \ | ||
| Default mode output: | \ | |
| 2 | ANSI mode output: | \ |
| Syntax error: failed at position 57; |
| ||
|Example 3: When using a full join, the output of the join key is data from both tables |
|SQL ||SELECT k FROM (SELECT 1 as k) FULL JOIN (SELECT 2 as k) USING k; || |\
| \ | ||
| Default mode output: | \ | |
| 1 | \ | |
| 2 | ANSI mode output: | \ |
| Syntax error: failed at position 57; |
In default mode, when the join uses a key with the same alias, the alias is visible to the left table. This feature is disabled in ANSI mode.
| ||
|Example: |
|SQL ||SELECT a + 1 AS k FROM (SELECT 1 as a) JOIN (SELECT 2::UInt16 AS k) USING k; || |\
| \ | ||
| Default mode output: | \ | |
| 2 | ANSI mode output: | \ |
| DB::Exception: Can not find column 'k' in join left side |
In ANSI mode, hash join, nested loop join, and merge join are supported.
Example:
CREATE TABLE nse_lhs (key int, value Nullable(UInt8)) ENGINE=CnchMergeTree order by key; CREATE TABLE nse_rhs (key int, value Nullable(UInt8)) ENGINE=CnchMergeTree order by key; INSERT INTO nse_lhs VALUES (1,1) (2, 2) (3, NULL) (4, NULL) (5,6) (6, NULL); INSERT INTO nse_rhs VALUES (1,1) (2, NULL) (3, 2) (4, NULL) (5,7) (6, 0); select '# Null safe join (equi hash join)'; SELECT key, value FROM nse_lhs JOIN nse_rhs ON nse_lhs.key=nse_rhs.key AND nse_rhs.value IS NOT DISTINCT FROM nse_lhs.value; select ''; SET join_algorithm='partial_merge'; select '# Null safe join (merge join)'; SELECT key, value FROM nse_lhs JOIN nse_rhs ON nse_lhs.key=nse_rhs.key AND nse_rhs.value<=>nse_lhs.value; SET join_algorithm='nested_loop'; select '# Null safe join (nested loop join)'; SELECT key, value FROM nse_lhs JOIN nse_rhs ON nse_lhs.key=nse_rhs.key AND nse_rhs.value<=>nse_lhs.value; SQL
--ANSI mode output: # USING <=> hash 1 1 4 \N# USING <=> partial_merge 1 1 4 \N# USING <=> nested_loop 1 1 4 \N
In default mode, for union / intersect / except operations, if all / distinct (deduplication) semantics are not explicitly specified, the default is all semantics; in ANSI mode, the default is distinct semantics.
| ||
|Example: |
|SQL ||SELECT 1 UNION SELECT 1; || |\
| \ | ||
| Default mode output: | \ | |
| 1 | \ | |
| 1 | ANSI mode output: | \ |
| 1 |