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

208 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 条件函数 {#tiao-jian-han-shu}
## if {#if}
控制条件分支。 与大多数系统不同ClickHouse始终评估两个表达式 `then``else`
**语法**
``` sql
SELECT if(cond, then, else)
```
如果条件 `cond` 的计算结果为非零值,则返回表达式 `then` 的结果,并且跳过表达式 `else` 的结果(如果存在)。 如果 `cond` 为零或 `NULL`,则将跳过 `then` 表达式的结果,并返回 `else` 表达式的结果(如果存在)。
您可以使用[short_circuit_function_evaluation](../../operations/settings/settings.md#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` - 如果不满足条件则返回的表达式。
**返回值**
该函数执行 `then` 和 `else` 表达式并返回其结果,这取决于条件 `cond` 最终是否为零。
**示例**
查询:
``` sql
SELECT if(1, plus(2, 2), plus(2, 6))
```
结果:
``` text
┌─plus(2, 2)─┐
│ 4 │
└────────────┘
```
查询:
``` sql
SELECT if(0, plus(2, 2), plus(2, 6))
```
结果:
``` text
┌─plus(2, 6)─┐
│ 8 │
└────────────┘
```
- `then` 和 `else` 必须具有最低的通用类型。
**示例:**
给定表`LEFT_RIGHT`:
``` sql
SELECT *
FROM LEFT_RIGHT
┌─left─┬─right─┐
│ ᴺᵁᴸᴸ │ 4 │
│ 1 │ 3 │
│ 2 │ 2 │
│ 3 │ 1 │
│ 4 │ ᴺᵁᴸᴸ │
└──────┴───────┘
```
下面的查询比较了 `left``right` 的值:
``` sql
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值](#null-values-in-conditionals) 部分。
## 三元运算符 {#ternary-operator}
与 `if` 函数相同。
语法: `cond ? then : else`
如果`cond = 0`则返回`then`,如果`cond = 0`则返回`else`。
- `cond`必须是`UInt8`类型,`then`和`else`必须存在最低的共同类型。
- `then`和`else`可以是`NULL`
**参考**
- [ifNotFinite](../../sql-reference/functions/other-functions.md#ifnotfinite)。
## multiIf {#multiif}
允许您在查询中更紧凑地编写[CASE](../operators/index.md#operator_case)运算符。
**语法**
``` sql
multiIf(cond_1, then_1, cond_2, then_2, ..., else)
```
您可以使用[short_circuit_function_evaluation](../../operations/settings/settings.md#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`
``` sql
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 │
└──────┴───────┴─────────────────┘
```
## 直接使用条件结果 {#using-conditional-results-directly}
条件结果始终为 `0`、 `1` 或 `NULL`。 因此,你可以像这样直接使用条件结果:
``` sql
SELECT left < right AS is_small
FROM LEFT_RIGHT
┌─is_small─┐
│ ᴺᵁᴸᴸ │
│ 1 │
│ 0 │
│ 0 │
│ ᴺᵁᴸᴸ │
└──────────┘
```
## 条件中的NULL值 {#null-values-in-conditionals}
当条件中包含 `NULL` 值时,结果也将为 `NULL`
``` sql
SELECT
NULL < 1,
2 < NULL,
NULL < NULL,
NULL = NULL
┌─less(NULL, 1)─┬─less(2, NULL)─┬─less(NULL, NULL)─┬─equals(NULL, NULL)─┐
ᴺᵁᴸᴸ ᴺᵁᴸᴸ ᴺᵁᴸᴸ ᴺᵁᴸᴸ
└───────────────┴───────────────┴──────────────────┴────────────────────┘
```
因此,如果类型是 `Nullable`,你应该仔细构造查询。
以下示例说明这一点。
``` sql
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 │
└──────┴───────┴──────────────────┘
```
[来源文章](https://clickhouse.com/docs/en/query_language/functions/conditional_functions/) <!--hide-->