ClickHouse/docs/zh/sql-reference/functions/conditional-functions.md

6.7 KiB
Raw Blame History

slug
/zh/sql-reference/functions/conditional-functions

条件函数

if

控制条件分支。 与大多数系统不同ClickHouse始终评估两个表达式 thenelse

语法

SELECT if(cond, then, else)

如果条件 cond 的计算结果为非零值,则返回表达式 then 的结果,并且跳过表达式 else 的结果(如果存在)。 如果 cond 为零或 NULL,则将跳过 then 表达式的结果,并返回 else 表达式的结果(如果存在)。

您可以使用short_circuit_function_evaluation 设置,来根据短路方案计算 if 函数。如果启用此设置,则仅在cond为真的时,加载then表达式,此时不加载else表达式。仅在cond为假时,加载else表达式,此时不加载then表达式。例如,执行查询SELECT if(number = 0, 0, intDiv(42, number)) FROM numbers(10)时不会抛出除以零的异常,因为intDiv(42, number)会仅对不满足条件number = 0的数字进行处理。

参数

  • cond 条件结果可以为零或不为零。 类型是 UInt8Nullable(UInt8) 或 NULL。
  • then - 如果满足条件则返回的表达式。
  • else - 如果不满足条件则返回的表达式。

返回值

该函数执行 thenelse 表达式并返回其结果,这取决于条件 cond 最终是否为零。

示例

查询:

SELECT if(1, plus(2, 2), plus(2, 6))

结果:

┌─plus(2, 2)─┐
│          4 │
└────────────┘

查询:

SELECT if(0, plus(2, 2), plus(2, 6))

结果:

┌─plus(2, 6)─┐
│          8 │
└────────────┘
  • thenelse 必须具有最低的通用类型。

示例:

给定表LEFT_RIGHT:

SELECT *
FROM LEFT_RIGHT

┌─left─┬─right─┐
 ᴺᵁᴸᴸ      4 
    1      3 
    2      2 
    3      1 
    4   ᴺᵁᴸᴸ 
└──────┴───────┘

下面的查询比较了 leftright 的值:

SELECT
    left,
    right,
    if(left < right, 'left is smaller than right', 'right is greater or equal than left') AS is_smaller
FROM LEFT_RIGHT
WHERE isNotNull(left) AND isNotNull(right)

┌─left─┬─right─┬─is_smaller──────────────────────────┐
    1      3  left is smaller than right          
    2      2  right is greater or equal than left 
    3      1  right is greater or equal than left 
└──────┴───────┴─────────────────────────────────────┘

注意:在此示例中未使用'NULL'值,请检查条件中的NULL值 部分。

三元运算符

if 函数相同。

语法: cond ? then : else

如果cond = 0则返回then,如果cond = 0则返回else

  • cond必须是UInt8类型,thenelse必须存在最低的共同类型。

  • thenelse可以是NULL

参考

multiIf

允许您在查询中更紧凑地编写CASE运算符。

语法

multiIf(cond_1, then_1, cond_2, then_2, ..., else)

您可以使用short_circuit_function_evaluation 设置,根据短路方案计算 multiIf 函数。如果启用此设置,则 then_i 表达式仅在 ((NOT cond_1) AND (NOT cond_2) AND ... AND (NOT cond_{i-1}) AND cond_i) 为真,cond_i 将仅对 ((NOT cond_1) AND (NOT cond_2) AND ... AND (NOT cond_{i-1})) 为真的行进行执行。例如执行查询“SELECT multiIf(number = 2, intDiv(1, number), number = 5) FROM numbers(10)”时不会抛出除以零的异常。

参数:

  • cond_N — 函数返回then_N的条件。
  • then_N — 执行时函数的结果。
  • else — 如果没有满足任何条件,则为函数的结果。

该函数接受2N + 1参数。

返回值

该函数返回值«then_N»或«else»之一具体取决于条件cond_N

示例

再次使用表 LEFT_RIGHT

SELECT
    left,
    right,
    multiIf(left < right, 'left is smaller', left > right, 'left is greater', left = right, 'Both equal', 'Null value') AS result
FROM LEFT_RIGHT

┌─left─┬─right─┬─result──────────┐
 ᴺᵁᴸᴸ      4  Null value      
    1      3  left is smaller 
    2      2  Both equal      
    3      1  left is greater 
    4   ᴺᵁᴸᴸ  Null value      
└──────┴───────┴─────────────────┘

直接使用条件结果

条件结果始终为 01NULL。 因此,你可以像这样直接使用条件结果:

SELECT left < right AS is_small
FROM LEFT_RIGHT

┌─is_small─┐
     ᴺᵁᴸᴸ 
        1 
        0 
        0 
     ᴺᵁᴸᴸ 
└──────────┘

条件中的NULL值

当条件中包含 NULL 值时,结果也将为 NULL

SELECT
    NULL < 1,
    2 < NULL,
    NULL < NULL,
    NULL = NULL

┌─less(NULL, 1)─┬─less(2, NULL)─┬─less(NULL, NULL)─┬─equals(NULL, NULL)─┐
 ᴺᵁᴸᴸ           ᴺᵁᴸᴸ           ᴺᵁᴸᴸ              ᴺᵁᴸᴸ               
└───────────────┴───────────────┴──────────────────┴────────────────────┘

因此,如果类型是 Nullable,你应该仔细构造查询。

以下示例说明这一点。

SELECT
    left,
    right,
    multiIf(left < right, 'left is smaller', left > right, 'right is smaller', 'Both equal') AS faulty_result
FROM LEFT_RIGHT

┌─left─┬─right─┬─faulty_result────┐
 ᴺᵁᴸᴸ      4  Both equal       
    1      3  left is smaller  
    2      2  Both equal       
    3      1  right is smaller 
    4   ᴺᵁᴸᴸ  Both equal       
└──────┴───────┴──────────────────┘