Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Funciones condicionales

Descripción general

Uso directo de resultados condicionales

Los condicionales siempre devuelven 0, 1 o NULL. Por lo tanto, puedes usar los resultados condicionales directamente así:

SELECT left < right AS is_small
FROM LEFT_RIGHT

Valores NULL en las expresiones condicionales

Cuando intervienen valores NULL en expresiones condicionales, el resultado también será NULL.

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

Por lo tanto, debes construir tus consultas con cuidado si los tipos son Nullable.

El siguiente ejemplo lo demuestra al no añadir una condición de igualdad a multiIf.

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

sentencia CASE

La expresión CASE en ClickHouse ofrece una lógica condicional similar al operador CASE de SQL. Evalúa las condiciones y devuelve valores en función de la primera condición que se cumple.

ClickHouse admite dos formas de CASE:

  1. CASE WHEN ... THEN ... ELSE ... END
    Esta forma ofrece total flexibilidad y se implementa internamente mediante la función multiIf. Cada condición se evalúa de forma independiente, y las expresiones pueden incluir valores no constantes.
SELECT
    number,
    CASE
        WHEN number % 2 = 0 THEN number + 1
        WHEN number % 2 = 1 THEN number * 10
        ELSE number
    END AS result
FROM system.numbers
WHERE number < 5;

-- se traduce a
SELECT
    number,
    multiIf((number % 2) = 0, number + 1, (number % 2) = 1, number * 10, number) AS result
FROM system.numbers
WHERE number < 5

  1. CASE <expr> WHEN <val1> THEN ... WHEN <val2> THEN ... ELSE ... END
    Esta forma más compacta está optimizada para comparar valores constantes y utiliza internamente caseWithExpression().

Por ejemplo, lo siguiente es válido:

SELECT
    number,
    CASE number
        WHEN 0 THEN 100
        WHEN 1 THEN 200
        ELSE 0
    END AS result
FROM system.numbers
WHERE number < 3;

-- se traduce a

SELECT
    number,
    caseWithExpression(number, 0, 100, 1, 200, 0) AS result
FROM system.numbers
WHERE number < 3

Esta forma tampoco requiere que las expresiones de retorno sean constantes.

SELECT
    number,
    CASE number
        WHEN 0 THEN number + 1
        WHEN 1 THEN number * 10
        ELSE number
    END
FROM system.numbers
WHERE number < 3;

-- se traduce a

SELECT
    number,
    caseWithExpression(number, 0, number + 1, 1, number * 10, number)
FROM system.numbers
WHERE number < 3

Consideraciones

ClickHouse determina el tipo de resultado de una expresión CASE (o su equivalente interno, como multiIf) antes de evaluar cualquier condición. Esto es importante cuando las expresiones de retorno difieren en el tipo, por ejemplo, con distintas zonas horarias o tipos numéricos.

  • El tipo de resultado se elige en función del tipo compatible más amplio entre todas las ramas.
  • Una vez elegido este tipo, todas las demás ramas se convierten implícitamente a él, aunque su lógica nunca llegue a ejecutarse en tiempo de ejecución.
  • En tipos como DateTime64, donde la zona horaria forma parte de la firma del tipo, esto puede dar lugar a comportamientos inesperados: la primera zona horaria encontrada puede usarse para todas las ramas, incluso cuando otras ramas especifican zonas horarias diferentes.

Por ejemplo, a continuación todas las filas devuelven la marca temporal en la zona horaria de la primera rama coincidente, es decir, Asia/Kolkata

SELECT
    number,
    CASE
        WHEN number = 0 THEN fromUnixTimestamp64Milli(0, 'Asia/Kolkata')
        WHEN number = 1 THEN fromUnixTimestamp64Milli(0, 'America/Los_Angeles')
        ELSE fromUnixTimestamp64Milli(0, 'UTC')
    END AS tz
FROM system.numbers
WHERE number < 3;

-- se traduce a

SELECT
    number,
    multiIf(number = 0, fromUnixTimestamp64Milli(0, 'Asia/Kolkata'), number = 1, fromUnixTimestamp64Milli(0, 'America/Los_Angeles'), fromUnixTimestamp64Milli(0, 'UTC')) AS tz
FROM system.numbers
WHERE number < 3

Aquí, ClickHouse ve varios tipos de retorno DateTime64(3, <timezone>). Infiere que el tipo común es DateTime64(3, 'Asia/Kolkata' por ser el primero que encuentra, y convierte implícitamente las demás ramas a este tipo.

Esto puede solucionarse convirtiéndolo en una cadena para conservar el formato de zona horaria previsto:

SELECT
    number,
    multiIf(
        number = 0, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'Asia/Kolkata'),
        number = 1, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'America/Los_Angeles'),
        formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'UTC')
    ) AS tz
FROM system.numbers
WHERE number < 3;

-- se traduce como

SELECT
    number,
    multiIf(
        number = 0, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'Asia/Kolkata'),
        number = 1, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'America/Los_Angeles'),
        formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'UTC')
    ) AS tz
FROM system.numbers
WHERE number < 3

clamp

Introducido en: v24.5.0

Limita un valor para que se mantenga dentro de los límites mínimo y máximo especificados.

Si el valor es menor que el mínimo, devuelve el mínimo. Si el valor es mayor que el máximo, devuelve el máximo. De lo contrario, devuelve el propio valor.

Todos los argumentos deben ser de tipos comparables. El tipo de resultado es el tipo compatible de mayor tamaño entre todos los argumentos.

Sintaxis

clamp(value, min, max)

Argumentos

  • value — El valor que se va a acotar. - min — El límite mínimo. - max — El límite máximo.

Valor devuelto

Devuelve el valor restringido al rango [min, max].

Ejemplos

Uso básico

SELECT clamp(5, 1, 10) AS result;
┌─result─┐
│      5 │
└────────┘

Valor inferior al mínimo

SELECT clamp(-3, 0, 7) AS result;
┌─result─┐
│      0 │
└────────┘

Valor superior al máximo

SELECT clamp(15, 0, 7) AS result;
┌─result─┐
│      7 │
└────────┘

greatest

Introducido en: v1.1.0

Devuelve el valor más alto entre los argumentos. Los argumentos NULL se ignoran.

  • Para arrays, devuelve el array lexicográficamente mayor.
  • Para los tipos DateTime, el tipo del resultado se promueve al tipo más grande (p. ej., DateTime64 si se mezcla con DateTime32).

Sintaxis

greatest(x1[, x2, ...])

Argumentos

  • x1[, x2, ...] — Uno o varios valores para comparar. Todos los argumentos deben ser de tipos comparables. Any

Valor devuelto

Devuelve el mayor valor entre los argumentos, promovido al tipo compatible de mayor tamaño. Any

Ejemplos

Tipos numéricos

-- The type returned is a Float64 as the UInt8 must be promoted to 64 bit for the comparison.
SELECT greatest(1, 2, toUInt8(3), 3.) AS result, toTypeName(result) AS type;
┌─result─┬─type────┐
│      3 │ Float64 │
└────────┴─────────┘

Arrays

SELECT greatest(['hello'], ['there'], ['world']);
┌─greatest(['hello'], ['there'], ['world'])─┐
│ ['world']                                 │
└───────────────────────────────────────────┘

Tipos de DateTime

-- The type returned is a DateTime64 as the DateTime32 must be promoted to 64 bit for the comparison.
SELECT greatest(toDateTime32('2025-01-02 12:00:00'), toDateTime64('2025-01-01 12:00:00.000', 3));
┌─greatest(toDateTime32('2025-01-02 12:00:00'), toDateTime64('2025-01-01 12:00:00.000', 3))─┐
│                                                                   2025-01-02 12:00:00.000 │
└───────────────────────────────────────────────────────────────────────────────────────────┘

if

Introducido en: v1.1.0

Realiza una bifurcación condicional.

  • Si la condición cond se evalúa como un valor distinto de cero, la función devuelve el resultado de la expresión then.
  • Si cond se evalúa como cero o NULL, se devuelve el resultado de la expresión else.

La configuración short_circuit_function_evaluation controla si se utiliza la evaluación de cortocircuito.

Si está habilitada, la expresión then se evalúa solo en las filas en las que cond es verdadero, y la expresión else, en las que cond es falso.

Por ejemplo, con la evaluación de cortocircuito, no se produce ninguna excepción por división entre cero al ejecutar la siguiente consulta:

SELECT if(number = 0, 0, intDiv(42, number)) FROM numbers(10)

then y else deben ser de tipo similar.

Sintaxis

if(cond, then, else)

Argumentos

  • cond — La condición evaluada. UInt8 o Nullable(UInt8) o NULL
  • then — La expresión que se devuelve si cond es verdadera. - else — La expresión que se devuelve si cond es falsa o NULL.

Valor devuelto

El resultado de las expresiones then o else, según la condición cond.

Ejemplos

Ejemplo de uso

SELECT if(1, 2 + 2, 2 + 6) AS res;
┌─res─┐
│   4 │
└─────┘

least

Introducido en: v1.1.0

Devuelve el valor más pequeño entre los argumentos. Los argumentos NULL se ignoran.

  • Para arrays, devuelve el array menor en orden lexicográfico.
  • Para los tipos DateTime, el tipo de resultado es promovido al tipo más grande (p. ej., DateTime64 si se mezcla con DateTime32).

Sintaxis

least(x1[, x2, ...])

Argumentos

  • x1[, x2, ...] — Un único valor o varios valores para comparar. Todos los argumentos deben ser de tipos comparables. Any

Valor devuelto

Devuelve el menor valor de entre los argumentos, promovido al tipo compatible de mayor tamaño. Any

Ejemplos

Tipos numéricos

-- The type returned is a Float64 as the UInt8 must be promoted to 64 bit for the comparison.
SELECT least(1, 2, toUInt8(3), 3.) AS result, toTypeName(result) AS type;
┌─result─┬─type────┐
│      1 │ Float64 │
└────────┴─────────┘

Arrays

SELECT least(['hello'], ['there'], ['world']);
┌─least(['hello'], ['there'], ['world'])─┐
│ ['hello']                              │
└────────────────────────────────────────┘

Tipos de DateTime

-- The type returned is a DateTime64 as the DateTime32 must be promoted to 64 bit for the comparison.
SELECT least(toDateTime32('2025-01-02 12:00:00'), toDateTime64('2025-01-01 12:00:00.000', 3));
┌─least(toDateTime32('2025-01-02 12:00:00'), toDateTime64('2025-01-01 12:00:00.000', 3))─┐
│                                                                2025-01-01 12:00:00.000 │
└────────────────────────────────────────────────────────────────────────────────────────┘

multiIf

Introducido en: v1.1.0

Permite escribir el operador CASE de forma más compacta en la consulta. Evalúa cada condición en orden. Para la primera condición que sea verdadera (distinta de cero y no NULL), devuelve el valor de la rama correspondiente. Si ninguna de las condiciones es verdadera, devuelve el valor de else.

El ajuste short_circuit_function_evaluation controla si se utiliza la evaluación de cortocircuito. Si está habilitada, la expresión then_i se evalúa solo en las filas donde ((NOT cond_1) AND ... AND (NOT cond_{i-1}) AND cond_i) es verdadera.

Por ejemplo, con la evaluación de cortocircuito, no se lanza ninguna excepción por división entre cero al ejecutar la siguiente consulta:

SELECT multiIf(number = 2, intDiv(1, number), number = 5) FROM numbers(10)

Todas las expresiones de las ramas y de else deben tener un supertipo común. Las condiciones NULL se tratan como falsas.

Sintaxis

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

Alias: caseWithoutExpression, caseWithoutExpr

Argumentos

  • cond_N — La enésima condición evaluada que determina si se devuelve then_N. UInt8 o Nullable(UInt8) o NULL
  • then_N — El resultado de la función cuando cond_N es verdadero. - else — El resultado de la función si ninguna condición es verdadera.

Valor devuelto

Devuelve el resultado de then_N para el cond_N que se cumpla; en caso contrario, devuelve el valor de else.

Ejemplos

Ejemplo de uso

CREATE TABLE LEFT_RIGHT (left Nullable(UInt8), right Nullable(UInt8)) ENGINE = Memory;
INSERT INTO LEFT_RIGHT VALUES (NULL, 4), (1, 3), (2, 2), (3, 1), (4, NULL);

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      │
└──────┴───────┴─────────────────┘
Navigation