> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-trino-dialect.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Documentación de la cláusula PREWHERE

# Cláusula PREWHERE

`PREWHERE` puede hacer que el filtrado sea más eficiente al reducir la cantidad de datos leídos. De forma predeterminada, ClickHouse aplica esta optimización incluso cuando una consulta no especifica explícitamente `PREWHERE`, trasladando las condiciones aptas de [`WHERE`](/es/reference/statements/select/where) a `PREWHERE`. Puede especificar `PREWHERE` explícitamente para controlar qué condiciones se aplican en esta fase.

Con `PREWHERE`, ClickHouse primero lee solo las columnas necesarias para evaluar la condición. Después, lee las demás columnas requeridas por la consulta únicamente en los bloques que contienen al menos una fila coincidente. Esto puede reducir la cantidad de datos leídos cuando la condición usa menos columnas que el resto de la consulta y descarta muchos bloques.

<div id="controlling-prewhere-manually">
  ## Control manual de `PREWHERE`
</div>

Especifique `PREWHERE` manualmente cuando una condición haga referencia a un número reducido de columnas y descarte muchas filas. Esto puede reducir la cantidad de datos que se leen de las columnas restantes.

Una consulta puede contener tanto `PREWHERE` como `WHERE`. En este caso, `PREWHERE` se evalúa primero.

Establezca [`optimize_move_to_prewhere`](/es/reference/settings/session-settings/optimize-move-to-prewhere#optimize_move_to_prewhere) en `0` para impedir que ClickHouse mueva automáticamente condiciones de `WHERE` a `PREWHERE`.

En las consultas con el modificador [`FINAL`](/es/reference/statements/select/from#final-modifier), ClickHouse mueve condiciones de `WHERE` a `PREWHERE` solo cuando están habilitados tanto [`optimize_move_to_prewhere`](/es/reference/settings/session-settings/optimize-move-to-prewhere#optimize_move_to_prewhere) como [`optimize_move_to_prewhere_if_final`](/es/reference/settings/session-settings/optimize-move-to-prewhere#optimize_move_to_prewhere_if_final).

<Note>
  De forma predeterminada, `PREWHERE` se evalúa antes de `FINAL`, por lo que las consultas `FROM ... FINAL` pueden producir resultados inesperados cuando `PREWHERE` hace referencia a columnas que no forman parte de la clave `ORDER BY` de la tabla.
</Note>

<div id="prewhere-with-join">
  ## `PREWHERE` con `JOIN`
</div>

Una condición `PREWHERE` en una consulta con un [`JOIN`](/es/reference/statements/select/join) puede hacer referencia directamente a columnas de una sola tabla como máximo. ClickHouse aplica la condición a las filas de esa tabla antes de que lleguen a la unión.

En cambio, una condición `WHERE` filtra lógicamente el resultado de la unión, aunque el optimizador puede aplicarla antes de la unión si hacerlo no cambia el resultado. Por lo tanto, usar la misma condición en `PREWHERE` y `WHERE` puede producir resultados diferentes, especialmente con uniones externas.

El siguiente ejemplo crea dos tablas para mostrar esta diferencia:

```sql theme={null}
CREATE TABLE table_1
(
    `id` UInt32,
    `value` String
)
ENGINE = MergeTree
ORDER BY id;

CREATE TABLE table_2
(
    `id` UInt32,
    `value` String
)
ENGINE = MergeTree
ORDER BY id;

INSERT INTO table_1 VALUES (1, 'a'), (2, 'b'), (3, 'c');
INSERT INTO table_2 VALUES (1, 'x'), (2, 'y'), (3, 'z');
```

En la primera consulta, `PREWHERE` filtra `table_2` antes del `LEFT JOIN`, por lo que la fila de `table_1` con `id = 1` queda sin coincidencia:

```sql theme={null}
SELECT
    table_1.id,
    table_1.value,
    table_2.value
FROM table_1
LEFT JOIN table_2 ON table_1.id = table_2.id
PREWHERE table_2.id >= 2
ORDER BY table_1.id;
```

```text theme={null}
   ┌─id─┬─value─┬─table_2.value─┐
1. │  1 │ a     │               │
2. │  2 │ b     │ y             │
3. │  3 │ c     │ z             │
   └────┴───────┴───────────────┘
```

Usar la misma condición en `WHERE` filtra el resultado de la unión y elimina la fila con `id = 1`:

```sql theme={null}
SELECT
    table_1.id,
    table_1.value,
    table_2.value
FROM table_1
LEFT JOIN table_2 ON table_1.id = table_2.id
WHERE table_2.id >= 2
ORDER BY table_1.id;
```

```text theme={null}
   ┌─id─┬─value─┬─table_2.value─┐
1. │  2 │ b     │ y             │
2. │  3 │ c     │ z             │
   └────┴───────┴───────────────┘
```

<div id="limitations">
  ## Limitaciones
</div>

`PREWHERE` solo se admite en tablas de la familia [\*MergeTree](/es/reference/engines/table-engines/mergetree-family/index).

<div id="example">
  ## Ejemplo
</div>

```sql theme={null}
CREATE TABLE mydata
(
    `A` Int64,
    `B` Int8,
    `C` String
)
ENGINE = MergeTree
ORDER BY A AS
SELECT
    number,
    0,
    if(number between 1000 and 2000, 'x', toString(number))
FROM numbers(10000000);

SELECT count()
FROM mydata
WHERE (B = 0) AND (C = 'x');

1 row in set. Elapsed: 0.074 sec. Processed 10.00 million rows, 168.89 MB (134.98 million rows/s., 2.28 GB/s.)

-- Enable tracing to see which predicates are moved to PREWHERE.
set send_logs_level='debug';

MergeTreeWhereOptimizer: condition "B = 0" moved to PREWHERE  
-- ClickHouse automatically moves B = 0 to PREWHERE, but this condition does not filter any rows because B is always 0.

-- Move the more selective C = 'x' predicate to PREWHERE.

SELECT count()
FROM mydata
PREWHERE C = 'x'
WHERE B = 0;

1 row in set. Elapsed: 0.069 sec. Processed 10.00 million rows, 158.89 MB (144.90 million rows/s., 2.30 GB/s.)

-- The query with manually specified PREWHERE processes slightly less data: 158.89 MB instead of 168.89 MB.
```
