Saltar al contenido principal

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

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

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

┌─less(NULL, 1)─┬─less(2, NULL)─┬─less(NULL, NULL)─┬─equals(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

┌─left─┬─right─┬─faulty_result────┐
│ ᴺᵁᴸᴸ │     4Both equal       │
13 │ left is smaller  │
22Both equal       │
31 │ right is smaller │
4 │  ᴺᵁᴸᴸ │ Both equal       │
└──────┴───────┴──────────────────┘

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

┌─number─┬─result─┐
01
110
23
330
45
└────────┴────────┘

5 rows in set. Elapsed: 0.002 sec.
  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

┌─number─┬─result─┐
0100
1200
20
└────────┴────────┘

3 rows in set. Elapsed: 0.002 sec.
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

┌─number─┬─caseWithExpr⋯0), number)─┐
01
110
22
└────────┴──────────────────────────┘

3 rows in set. Elapsed: 0.001 sec.

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

┌─number─┬──────────────────────tz─┐
01970-01-01 05:30:00.000
11970-01-01 05:30:00.000
21970-01-01 05:30:00.000
└────────┴─────────────────────────┘

3 rows in set. Elapsed: 0.011 sec.
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

┌─number─┬─tz──────────────────┐
01970-01-01 05:30:00
11969-12-31 16:00:00
21970-01-01 00:00:00
└────────┴─────────────────────┘

3 filas en el conjunto. Tiempo transcurrido: 0.002 seg.

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
Query
SELECT clamp(5, 1, 10) AS result;
Response
┌─result─┐
│      5 │
└────────┘
Valor inferior al mínimo
Query
SELECT clamp(-3, 0, 7) AS result;
Response
┌─result─┐
│      0 │
└────────┘
Valor superior al máximo
Query
SELECT clamp(15, 0, 7) AS result;
Response
┌─result─┐
│      7 │
└────────┘

greatest

Introducido en: v1.1.0 Devuelve el valor máximo 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 amplía al tipo más grande (p. ej., DateTime64 si se mezcla con DateTime32).
Use la configuración least_greatest_legacy_null_behavior para cambiar el comportamiento de NULLLa versión 24.12 introdujo un cambio incompatible con versiones anteriores por el que los valores NULL se ignoran, mientras que antes devolvía NULL si uno de los argumentos era NULL. Para conservar el comportamiento anterior, establezca la configuración least_greatest_legacy_null_behavior (valor predeterminado: false) en true.
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 valor más alto entre los argumentos, promovido al tipo compatible de mayor tamaño. Any Ejemplos Tipos numéricos
Query
SELECT greatest(1, 2, toUInt8(3), 3.) AS result, toTypeName(result) AS type;
-- El tipo devuelto es Float64 ya que el UInt8 debe promoverse a 64 bits para la comparación.
Response
┌─result─┬─type────┐
│      3 │ Float64 │
└────────┴─────────┘
Arrays
Query
SELECT greatest(['hello'], ['there'], ['world']);
Response
┌─greatest(['hello'], ['there'], ['world'])─┐
│ ['world']                                 │
└───────────────────────────────────────────┘
Tipos de DateTime
Query
SELECT greatest(toDateTime32(now() + toIntervalDay(1)), toDateTime64(now(), 3));
-- El tipo devuelto es DateTime64 ya que DateTime32 debe ascenderse a 64 bits para la comparación.
Response
┌─greatest(toD⋯(now(), 3))─┐
│  2025-05-28 15:50:53.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
Query
SELECT if(1, 2 + 2, 2 + 6) AS res;
Response
┌─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 se promueve al tipo más grande (p. ej., DateTime64 si se mezcla con DateTime32).
Use la configuración least_greatest_legacy_null_behavior para cambiar el comportamiento de NULLLa versión 24.12 introdujo un cambio no retrocompatible por el que los valores NULL se ignoran, mientras que antes devolvía NULL si uno de los argumentos era NULL. Para conservar el comportamiento anterior, establezca la configuración least_greatest_legacy_null_behavior (valor predeterminado: false) en true.
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, convertido al tipo compatible de mayor tamaño. Any Ejemplos Tipos numéricos
Query
SELECT least(1, 2, toUInt8(3), 3.) AS result, toTypeName(result) AS type;
-- El tipo devuelto es Float64 ya que el UInt8 debe promoverse a 64 bits para la comparación.
Response
┌─result─┬─type────┐
│      1 │ Float64 │
└────────┴─────────┘
Arrays
Query
SELECT least(['hello'], ['there'], ['world']);
Response
┌─least(['hell⋯ ['world'])─┐
│ ['hello']                │
└──────────────────────────┘
Tipos de DateTime
Query
SELECT least(toDateTime32(now() + toIntervalDay(1)), toDateTime64(now(), 3));
-- El tipo devuelto es DateTime64 ya que DateTime32 debe promoverse a 64 bits para la comparación.
Response
┌─least(toDate⋯(now(), 3))─┐
│  2025-05-27 15:55:20.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
Query
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;
Response
┌─left─┬─right─┬─result──────────┐
│ ᴺᵁᴸᴸ │     4 │ Null value      │
│    1 │     3 │ left is smaller │
│    2 │     2 │ Both equal      │
│    3 │     1 │ left is greater │
│    4 │  ᴺᵁᴸᴸ │ Null value      │
└──────┴───────┴─────────────────┘
Última modificación el 10 de junio de 2026