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

> Documentación sobre CREATE VIEW

# CREATE VIEW

export const CloudNotSupportedBadge = () => {
  return <div className="cloudNotSupportedBadge">
            <div className="cloudNotSupportedIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.5" d="M6.33366 12.6666L12.3739 12.6667C13.6593 12.6667 14.7073 11.6187 14.7073 10.3334C14.7073 9.04804 13.6593 8.00003 12.3739 8.00003C12.3739 8.00003 12.3337 7.66659 12.0003 7.33325M10.667 5.33322C8.00033 2.33325 4.45395 4.78537 4.14195 6.68203C2.55728 6.7627 1.29395 8.06203 1.29395 9.6667C1.29395 11.3234 2.66699 12.6666 4.00033 12.6666" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.5" d="M2.66699 14L12.0003 4.66663" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>

        </div>
            Not supported in ClickHouse Cloud
        </div>;
};

export const DeprecatedBadge = () => {
  return <div className="deprecatedBadge">
            <div className="deprecatedIcon">
            <svg width="14" height="10" viewBox="0 0 14 10" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M13 0H1C0.734784 0 0.48043 0.105357 0.292893 0.292893C0.105357 0.48043 0 0.734784 0 1V2.5C0 2.76522 0.105357 3.01957 0.292893 3.20711C0.48043 3.39464 0.734784 3.5 1 3.5V9C1 9.26522 1.10536 9.51957 1.29289 9.70711C1.48043 9.89464 1.73478 10 2 10H12C12.2652 10 12.5196 9.89464 12.7071 9.70711C12.8946 9.51957 13 9.26522 13 9V3.5C13.2652 3.5 13.5196 3.39464 13.7071 3.20711C13.8946 3.01957 14 2.76522 14 2.5V1C14 0.734784 13.8946 0.48043 13.7071 0.292893C13.5196 0.105357 13.2652 0 13 0ZM12 9H2V3.5H12V9ZM13 2.5H1V1H13V2.5ZM5 5.5C5 5.36739 5.05268 5.24021 5.14645 5.14645C5.24021 5.05268 5.36739 5 5.5 5H8.5C8.63261 5 8.75979 5.05268 8.85355 5.14645C8.94732 5.24021 9 5.36739 9 5.5C9 5.63261 8.94732 5.75979 8.85355 5.85355C8.75979 5.94732 8.63261 6 8.5 6H5.5C5.36739 6 5.24021 5.94732 5.14645 5.85355C5.05268 5.75979 5 5.63261 5 5.5Z" fill="currentColor" />
            </svg>
        </div>
            Deprecated feature
        </div>;
};

export const ExperimentalBadge = () => {
  return <div className="experimentalBadge">
            <div className="experimentalIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.25" d="M5.5 2H10.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M9.50015 2V6.19625L13.4283 12.7425C13.4738 12.8183 13.4985 12.9049 13.4996 12.9934C13.5008 13.0818 13.4785 13.169 13.435 13.246C13.3914 13.323 13.3283 13.3871 13.2519 13.4317C13.1755 13.4764 13.0886 13.4999 13.0002 13.5H3.00015C2.91164 13.5 2.8247 13.4766 2.74822 13.432C2.67174 13.3874 2.60847 13.3233 2.56487 13.2463C2.52126 13.1693 2.49889 13.082 2.50004 12.9935C2.50119 12.905 2.52582 12.8184 2.5714 12.7425L6.50015 6.19625V2" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M4.47656 9.56754C5.30344 9.41254 6.47656 9.47942 7.99969 10.25C10.0153 11.2707 11.4216 11.0569 12.2184 10.7282" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            Experimental feature. <u><a href="/docs/beta-and-experimental-features#experimental-features">Learn more.</a></u>
        </div>;
};

Crea una nueva vista. Las vistas pueden ser [normales](#normal-view), [materializadas](#materialized-view), [materializadas actualizables](#refreshable-materialized-view) y [de ventana](/es/reference/statements/create/view#window-view).

<div id="normal-view">
  ## Vista normal
</div>

Sintaxis:

```sql theme={null}
CREATE [OR REPLACE] VIEW [IF NOT EXISTS] [db.]table_name [(alias1 [, alias2 ...])] [ON CLUSTER cluster_name]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

Las vistas normales no almacenan datos. Simplemente leen de otra tabla en cada acceso. En otras palabras, una vista normal no es más que una consulta guardada. Al leer una vista, esta consulta guardada se usa como subconsulta en la cláusula [FROM](/es/reference/statements/select/from).

Como ejemplo, suponga que ha creado una vista:

```sql theme={null}
CREATE VIEW view AS SELECT ...
```

y escribir una consulta:

```sql theme={null}
SELECT a, b, c FROM view
```

Esta consulta equivale por completo a usar la subconsulta:

```sql theme={null}
SELECT a, b, c FROM (SELECT ...)
```

<div id="parameterized-view">
  ## Vista parametrizada
</div>

Las vistas parametrizadas son similares a las vistas normales, pero pueden crearse con parámetros que no se resuelven inmediatamente. Estas vistas pueden usarse con funciones de tabla, que especifican el nombre de la vista como nombre de la función y los valores de los parámetros como argumentos.

```sql theme={null}
CREATE VIEW view AS SELECT * FROM TABLE WHERE Column1={column1:datatype1} and Column2={column2:datatype2} ...
```

Lo anterior crea una vista para la tabla, que puede usarse como función de tabla al sustituir los parámetros, como se muestra a continuación.

```sql theme={null}
SELECT * FROM view(column1=value1, column2=value2 ...)
```

<div id="materialized-view">
  ## Vista materializada
</div>

```sql theme={null}
CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster_name] [TO[db.]name [(columns)]] [ENGINE = engine] [POPULATE]
[REFRESH ...]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

```sql theme={null}
CREATE OR REPLACE MATERIALIZED VIEW [db.]table_name [ON CLUSTER cluster_name] [TO[db.]name [(columns)]] [ENGINE = engine] [POPULATE]
[REFRESH ...]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

`OR REPLACE` e `IF NOT EXISTS` son mutuamente excluyentes: combinarlos da lugar a un error de sintaxis.

<div id="create-or-replace-materialized-view">
  ### CREATE OR REPLACE MATERIALIZED VIEW
</div>

`CREATE OR REPLACE MATERIALIZED VIEW` reemplaza de forma atómica una vista materializada existente y su tabla de almacenamiento subyacente (si la hay). La operación requiere un motor de base de datos `Atomic` o `Replicated`.

```sql theme={null}
CREATE OR REPLACE MATERIALIZED VIEW [db.]name [ON CLUSTER cluster]
[TO [db.]target_table]
[ENGINE = engine]
[POPULATE]
[REFRESH ...]
AS SELECT ...
```

Comportamientos clave:

* **Sin la cláusula `TO`**: se elimina la tabla interna anterior y se crea una nueva. Los datos existentes en la tabla interna se pierden, salvo que se especifique `POPULATE`.
* **Con la cláusula `TO`**: solo se reemplaza la definición de la vista; la tabla de destino y sus datos no se ven afectados.
* Compatible con `REFRESH`, `ON CLUSTER` y todas las opciones del motor. `POPULATE` solo se admite en bases de datos `Atomic`; se rechaza en bases de datos `Replicated` (consulte la nota sobre `POPULATE` más abajo).
* Requiere los privilegios `CREATE VIEW` y `DROP VIEW`.

<Note>
  `CREATE OR REPLACE MATERIALIZED VIEW` solo es compatible con los motores de base de datos `Atomic` o `Replicated`. No es compatible con el motor de base de datos `Ordinary`.
</Note>

**Ejemplos:**

```sql theme={null}
-- Crear una vista materializada con una tabla interna
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    AS SELECT x, sum(y) AS total FROM src GROUP BY x;

-- Reemplazar con una nueva definición (los datos de la tabla interna anterior se pierden)
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    AS SELECT x, count() AS cnt FROM src GROUP BY x;

-- Reemplazar con POPULATE para rellenar datos históricos desde la fuente existente
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    POPULATE
    AS SELECT x FROM src;

-- Reemplazar una vista materializada con tabla interna por una con cláusula TO (los datos del destino se conservan)
CREATE OR REPLACE MATERIALIZED VIEW mv TO target
    AS SELECT x FROM src;
```

<Tip>
  Aquí tienes una guía paso a paso sobre cómo usar [vistas materializadas](/es/concepts/features/materialized-views/cascading-materialized-views).
</Tip>

Las vistas materializadas almacenan los datos transformados por la consulta [SELECT](/es/reference/statements/select) correspondiente.

Al crear una vista materializada sin `TO [db].[table]`, debes especificar `ENGINE`: el motor de tabla para almacenar los datos.

Al crear una vista materializada con `TO [db].[table]`, tampoco puedes usar `POPULATE`.

Una vista materializada se implementa de la siguiente manera: al insertar datos en la tabla especificada en `SELECT`, una parte de los datos insertados se transforma mediante esta consulta `SELECT`, y el resultado se inserta en la vista.

<Note>
  Las vistas materializadas en ClickHouse usan **nombres de columna** en lugar del orden de las columnas durante la inserción en la tabla de destino. Si algunos nombres de columna no están presentes en el resultado de la consulta `SELECT`, ClickHouse usa un valor predeterminado, incluso si la columna no es [Nullable](/es/reference/data-types/nullable). Una práctica segura es añadir alias para cada columna al usar vistas materializadas.

  Las vistas materializadas en ClickHouse se implementan más bien como triggers de inserción. Si hay alguna agregación en la consulta de la vista, se aplica solo al lote de datos recién insertados. Cualquier cambio en los datos existentes de la tabla de origen (como update, delete, drop partition, etc.) no modifica la vista materializada.

  Las vistas materializadas en ClickHouse no tienen un comportamiento determinista en caso de error. Esto significa que los bloques que ya se hayan escrito se conservarán en la tabla de destino, pero no se conservarán los bloques posteriores al error.

  De forma predeterminada, si falla el envío a una de las vistas, la consulta `INSERT` también fallará, y es posible que algunos bloques no se escriban en la tabla de destino. Esto se puede cambiar usando la configuración `materialized_views_ignore_errors` (debes establecerla para la consulta `INSERT`); si configuras `materialized_views_ignore_errors=true`, se ignorará cualquier error al enviar a las vistas y todos los bloques se escribirán en la tabla de destino.

  Ten en cuenta también que `materialized_views_ignore_errors` está establecido en `true` de forma predeterminada para las tablas `system.*_log`.
</Note>

Si especificas `POPULATE`, los datos existentes de la tabla se insertan en la vista al crearla, como si se hiciera un `CREATE TABLE ... AS SELECT ...`. De lo contrario, la consulta contiene solo los datos insertados en la tabla después de crear la vista. **No recomendamos** usar `POPULATE`, ya que los datos insertados en la tabla durante la creación de la vista no se insertarán en ella.

<Note>
  Dado que `POPULATE` funciona como `CREATE TABLE ... AS SELECT ...`, tiene limitaciones:

  * No es compatible con base de datos `Replicated`
  * No es compatible con ClickHouse Cloud

  En su lugar, se puede usar un `INSERT ... SELECT` por separado.
</Note>

Una consulta `SELECT` puede contener `DISTINCT`, `GROUP BY`, `ORDER BY`, `LIMIT`. Tenga en cuenta que las transformaciones correspondientes se realizan de forma independiente en cada bloque de datos insertados. Por ejemplo, si se establece `GROUP BY`, los datos se agregan durante la inserción, pero solo dentro de un único paquete de datos insertados. Los datos no se volverán a agregar después. La excepción es cuando se usa un `ENGINE` que realiza la agregación de datos por sí mismo, como `SummingMergeTree`.

Si la vista materializada usa la construcción `TO [db.]name`, puede aplicar `DETACH` a la vista, ejecutar `ALTER` en la tabla de destino y luego hacer `ATTACH` de la vista previamente separada con `DETACH`.

Tenga en cuenta que la vista materializada se ve afectada por la configuración [optimize\_on\_insert](/es/reference/settings/session-settings#optimize_on_insert). Los datos se fusionan antes de insertarse en una vista.

Las vistas tienen el mismo aspecto que las tablas normales. Por ejemplo, aparecen en el resultado de la consulta `SHOW TABLES`.

Para eliminar una vista, use [DROP VIEW](/es/reference/statements/drop#drop-view). Aunque `DROP TABLE` también funciona para las VIEW.

<div id="sql_security">
  ## SQL security
</div>

`DEFINER` y `SQL SECURITY` permiten especificar qué usuario de ClickHouse se utilizará al ejecutar la consulta subyacente de la vista.
`SQL SECURITY` tiene tres valores válidos: `DEFINER`, `INVOKER` o `NONE`. Puede especificar cualquier usuario existente o `CURRENT_USER` en la cláusula `DEFINER`.

La siguiente tabla explica qué permisos se requieren para cada usuario al seleccionar datos de una vista.
Tenga en cuenta que, independientemente de la opción de SQL security, en todos los casos sigue siendo necesario tener `GRANT SELECT ON <view>` para poder leer de ella.

| Opción de SQL security | Vista                                                                           | Vista materializada                                                                                                                         |
| ---------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `DEFINER alice`        | `alice` debe tener el privilegio `SELECT` sobre la tabla fuente de la vista.    | `alice` debe tener el privilegio `SELECT` sobre la tabla fuente de la vista y el privilegio `INSERT` sobre la tabla de destino de la vista. |
| `INVOKER`              | El usuario debe tener el privilegio `SELECT` sobre la tabla fuente de la vista. | No se puede especificar `SQL SECURITY INVOKER` para las vistas materializadas.                                                              |
| `NONE`                 | -                                                                               | -                                                                                                                                           |

<Note>
  `SQL SECURITY NONE` es una opción obsoleta. Cualquier usuario con permisos para crear vistas con `SQL SECURITY NONE` podrá ejecutar cualquier consulta arbitraria.
  Por lo tanto, es necesario tener `GRANT ALLOW SQL SECURITY NONE TO <user>` para crear una vista con esta opción.
</Note>

Si no se especifican `DEFINER`/`SQL SECURITY`, se usan los valores predeterminados:

* `SQL SECURITY`: `INVOKER` para las vistas normales y `DEFINER` para las vistas materializadas ([configurable en Settings](/es/reference/settings/session-settings#default_normal_view_sql_security))
* `DEFINER`: `CURRENT_USER` ([configurable en Settings](/es/reference/settings/session-settings#default_view_definer))

Si una vista se adjunta sin especificar `DEFINER`/`SQL SECURITY`, el valor predeterminado es `SQL SECURITY NONE` para la vista materializada y `SQL SECURITY INVOKER` para la vista normal.

Para cambiar SQL security de una vista existente, use

```sql theme={null}
ALTER TABLE MODIFY SQL SECURITY { DEFINER | INVOKER | NONE } [DEFINER = { user | CURRENT_USER }]
```

<div id="examples">
  ### Ejemplos
</div>

```sql theme={null}
CREATE VIEW test_view
DEFINER = alice SQL SECURITY DEFINER
AS SELECT ...
```

```sql theme={null}
CREATE VIEW test_view
SQL SECURITY INVOKER
AS SELECT ...
```

<div id="live-view">
  ## Live View
</div>

Esta función está obsoleta y se eliminará en el futuro.

Para mayor comodidad, la documentación anterior está disponible [aquí](https://pastila.nl/?00f32652/fdf07272a7b54bda7e13b919264e449f.md)

<div id="refreshable-materialized-view">
  ## Vista materializada actualizable
</div>

```sql theme={null}
CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
REFRESH EVERY|AFTER interval [OFFSET interval]
[RANDOMIZE FOR interval]
[DEPENDS ON [db.]name [, [db.]name [, ...]]]
[SETTINGS name = value [, name = value [, ...]]]
[APPEND]
[TO[db.]name] [(columns)] [ENGINE = engine]
[EMPTY]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

donde `interval` es una secuencia de intervalos simples:

```sql theme={null}
number SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|YEAR
```

Ejecuta periódicamente la consulta correspondiente y almacena su resultado en una tabla.

* Si se especifica `APPEND`, cada actualización inserta filas en la tabla sin eliminar las existentes. La inserción no es atómica, igual que en una consulta `INSERT INTO ... SELECT` normal.
* De lo contrario, cada actualización reemplaza atómicamente el contenido previo de la tabla.

Diferencias con las vistas materializadas normales no actualizables:

* No hay trigger de inserción. Cuando se insertan datos nuevos en la tabla especificada en `SELECT`, *no* se envían automáticamente a la vista materializada actualizable. En su lugar, los datos solo se insertan durante las ejecuciones de actualización periódicas o manuales.
* La consulta `SELECT` no tiene restricciones. Se permiten funciones de tabla (por ejemplo, `url()`), vistas, UNION y JOIN.

<Note>
  La configuración de la parte `REFRESH ... SETTINGS` de la consulta corresponde a los parámetros de actualización (por ejemplo, `refresh_retries`), y es distinta de la configuración normal (por ejemplo, `max_threads`). La configuración normal puede especificarse con `SETTINGS` al final de la consulta.
</Note>

<div id="refresh-schedule">
  ### Programación de actualización
</div>

Ejemplos de programación de actualización:

```sql theme={null}
REFRESH EVERY 1 DAY -- cada día, a medianoche (UTC)
REFRESH EVERY 1 MONTH -- el día 1 de cada mes, a medianoche
REFRESH EVERY 1 MONTH OFFSET 5 DAY 2 HOUR -- el día 6 de cada mes, a las 2:00 am
REFRESH EVERY 2 WEEK OFFSET 5 DAY 15 HOUR 10 MINUTE -- cada dos sábados, a las 3:10 pm
REFRESH EVERY 30 MINUTE -- a las 00:00, 00:30, 01:00, 01:30, etc.
REFRESH AFTER 30 MINUTE -- 30 minutos después de que finalice la actualización anterior, sin ajuste a la hora del día
-- REFRESH AFTER 1 HOUR OFFSET 1 MINUTE -- error de sintaxis, OFFSET no está permitido con AFTER
REFRESH EVERY 1 WEEK 2 DAYS -- cada 9 días, sin coincidir con ningún día específico de la semana ni del mes;
                            -- concretamente, cuando el número de día (desde el 1969-12-29) es divisible por 9
REFRESH EVERY 5 MONTHS -- cada 5 meses, en meses distintos cada año (ya que 12 no es divisible por 5);
                       -- concretamente, cuando el número de mes (desde 1970-01) es divisible por 5
```

`RANDOMIZE FOR` ajusta aleatoriamente el momento en que se realiza cada actualización, por ejemplo:

```sql theme={null}
REFRESH EVERY 1 DAY OFFSET 2 HOUR RANDOMIZE FOR 1 HOUR -- cada día a una hora aleatoria entre las 01:30 y las 02:30
```

Como máximo, puede haber una sola actualización en ejecución a la vez para una vista determinada. Por ejemplo, si una vista con `REFRESH EVERY 1 MINUTE` tarda 2 minutos en actualizarse, simplemente se actualizará cada 2 minutos. Si después se vuelve más rápida y empieza a actualizarse en 10 segundos, volverá a actualizarse cada minuto. (En particular, no se actualizará cada 10 segundos para compensar actualizaciones omitidas: no existe tal retraso acumulado).

Además, una actualización se inicia inmediatamente después de crear la vista materializada, a menos que se especifique `EMPTY` en la consulta `CREATE`. Si se especifica `EMPTY`, la primera actualización se realiza según la programación.

<div id="in-replicated-db">
  ### En una DB Replicated
</div>

Si la vista materializada actualizable está en una [base de datos Replicated](/es/reference/engines/database-engines/replicated), las réplicas se coordinan entre sí para que solo una de ellas realice la actualización en cada momento programado. Se requiere el motor de tabla [ReplicatedMergeTree](/es/reference/engines/table-engines/mergetree-family/replication) para que todas las réplicas vean los datos generados por la actualización.

En modo `APPEND`, la coordinación puede deshabilitarse con `SETTINGS all_replicas = 1`. Esto hace que las réplicas realicen las actualizaciones de forma independiente. En este caso, ReplicatedMergeTree no es necesario.

En el modo no `APPEND`, solo se admite la actualización coordinada. Para una actualización no coordinada, use la base de datos `Atomic` y la consulta `CREATE ... ON CLUSTER` para crear vistas materializadas actualizables en todas las réplicas.

La coordinación se realiza mediante Keeper. La ruta del znode se determina mediante la configuración de servidor [default\_replica\_path](/es/reference/settings/server-settings/settings#default_replica_path).

<div id="refresh-dependencies">
  ### Dependencias de actualización
</div>

`DEPENDS ON` sincroniza las actualizaciones de distintas tablas. Por ejemplo, supongamos que hay una secuencia de dos vistas materializadas actualizables:

```sql theme={null}
CREATE MATERIALIZED VIEW source REFRESH EVERY 1 DAY AS SELECT * FROM url(...)
CREATE MATERIALIZED VIEW destination REFRESH EVERY 1 DAY AS SELECT ... FROM source
```

Sin `DEPENDS ON`, ambas vistas empezarán a actualizarse a medianoche, y `destination` normalmente verá en `source` los datos de ayer. Si añadimos una dependencia:

```sql theme={null}
CREATE MATERIALIZED VIEW destination REFRESH EVERY 1 DAY DEPENDS ON source AS SELECT ... FROM source
```

entonces la actualización de `destination` comenzará solo después de que haya finalizado la actualización de `source` de ese día, por lo que `destination` se basará en datos actualizados.

Alternativamente, se puede lograr el mismo resultado con:

```sql theme={null}
CREATE MATERIALIZED VIEW destination REFRESH AFTER 1 HOUR DEPENDS ON source AS SELECT ... FROM source
```

donde `1 HOUR` puede ser cualquier duración inferior al período de actualización de `source`. La tabla dependiente no se actualizará con más frecuencia que ninguna de sus dependencias. Esta es una forma válida de configurar una cadena de vistas actualizables sin especificar el período de actualización real más de una vez.

Algunos ejemplos más:

* `REFRESH EVERY 1 DAY OFFSET 10 MINUTE` (`destination`) depende de `REFRESH EVERY 1 DAY` (`source`)<br />
  Si la actualización de `source` tarda más de 10 minutos, `destination` esperará.
* `REFRESH EVERY 1 DAY OFFSET 1 HOUR` depende de `REFRESH EVERY 1 DAY OFFSET 23 HOUR`<br />
  Similar al caso anterior, aunque las actualizaciones correspondientes se produzcan en días naturales distintos.
  La actualización de `destination` del día `X+1` esperará a la actualización de `source` del día `X` (si tarda más de 2 horas).
* `REFRESH EVERY 2 HOUR` depende de `REFRESH EVERY 1 HOUR`<br />
  La actualización de `2 HOUR` se produce después de la de `1 HOUR` en horas alternas; por ejemplo, después de la
  actualización de medianoche, luego después de la de las 2 a. m., etc.
* `REFRESH EVERY 1 MINUTE` depende de `REFRESH EVERY 2 HOUR`<br />
  `destination` se actualiza una vez después de cada actualización de `source`, es decir, cada 2 horas. En la práctica, `1 MINUTE` se ignora.
* `REFRESH AFTER 1 HOUR` depende de `REFRESH AFTER 1 HOUR`<br />
  Actualmente, esto no se recomienda.

<Note>
  `DEPENDS ON` solo funciona entre vistas materializadas actualizables. Incluir una tabla normal en la lista `DEPENDS ON` impedirá que la vista llegue a actualizarse (las dependencias pueden eliminarse con `ALTER`; consulta [Cambio de los parámetros de actualización](#changing-refresh-parameters)).
</Note>

<div id="refresh-settings">
  ### Parámetros de actualización
</div>

Parámetros de actualización disponibles:

* `refresh_retries` - Cuántas veces reintentar si la consulta de actualización falla con una excepción. Si fallan todos los reintentos, se pasa a la siguiente hora de actualización programada. 0 significa que no hay reintentos; -1, que los reintentos son infinitos. Predeterminado: 2.
* `refresh_retry_initial_backoff_ms` - Retraso antes del primer reintento, si `refresh_retries` no es cero. Cada reintento posterior duplica el retraso, hasta `refresh_retry_max_backoff_ms`. Predeterminado: 100 ms.
* `refresh_retry_max_backoff_ms` - Límite del crecimiento exponencial del retraso entre intentos de actualización. Predeterminado: 60000 ms (1 minuto).
* `all_replicas` - En una [base de datos Replicated](/es/reference/engines/database-engines/replicated) con `APPEND`, controla si todas las réplicas se actualizan de forma independiente o si solo una réplica se actualiza en cada momento programado. No se puede cambiar después de crear la vista. Predeterminado: `false`.
* `prefer_dependency_replica` - Cuando la vista tiene `DEPENDS ON`, la réplica que ejecutó la actualización primaria tiene prioridad para ejecutar la actualización dependiente; las demás réplicas retrasan su intento en `prefer_dependency_replica_delay_ms`. Es útil con `SharedMergeTree` para evitar que el retraso de replicación provoque la falta de datos en cadenas de actualizaciones dependientes. Predeterminado: `false`.
* `prefer_dependency_replica_delay_ms` - Cuánto tiempo esperan las réplicas no preferidas antes de intentar ejecutar una actualización dependiente cuando `prefer_dependency_replica` está habilitado. Predeterminado: 2000 ms.

<div id="changing-refresh-parameters">
  ### Cambiar los parámetros de actualización
</div>

Los parámetros de actualización de una vista materializada actualizable existente se modifican mediante [`ALTER TABLE ... MODIFY REFRESH`](/es/reference/statements/alter/view#alter-table--modify-refresh-statement):

```sql theme={null}
ALTER TABLE [db.]name MODIFY REFRESH EVERY|AFTER ... [RANDOMIZE FOR ...] [DEPENDS ON ...] [SETTINGS ...]
```

La programación (`EVERY` o `AFTER`) es obligatoria: la sentencia siempre sustituye *todos* los parámetros de actualización —la programación, `RANDOMIZE FOR`, `DEPENDS ON` y los parámetros de actualización— por los especificados. Todo lo que se omita se restablece a su valor predeterminado (configuración) o se elimina (dependencias, aleatorización).

<Note>
  * Para cambiar solo los parámetros de actualización (por ejemplo, `refresh_retries`), repita la programación actual:

    ```sql theme={null}
    ALTER TABLE rmv MODIFY REFRESH EVERY 1 HOUR SETTINGS refresh_retries = 5;
    ```

  * `ALTER TABLE ... MODIFY SETTING refresh_retries = ...` no es compatible con las vistas materializadas; debe hacerse mediante `MODIFY REFRESH`.

  * No se admite añadir ni quitar `APPEND`.

  * La configuración `all_replicas` no puede cambiarse después de la creación.
</Note>

Ejemplos:

```sql theme={null}
-- Cambiar el horario, eliminar la configuración y las dependencias existentes.
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE;

-- Cambiar el horario y ajustar el comportamiento de reintentos.
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE
SETTINGS refresh_retries = 5,
         refresh_retry_initial_backoff_ms = 500,
         refresh_retry_max_backoff_ms = 60000;

-- Mantener la dependencia al cambiar el período.
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR DEPENDS ON other_rmv;

-- Eliminar la dependencia omitiendo `DEPENDS ON`.
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR;
```

<div id="other-operations">
  ### Otras operaciones
</div>

El estado de todas las vistas materializadas actualizables está disponible en la tabla [`system.view_refreshes`](/es/reference/system-tables/view_refreshes). En particular, incluye el progreso de la actualización (si está en curso), la hora de la última y de la próxima actualización, y el mensaje de excepción si una actualización falló.

Para detener, iniciar, activar o cancelar actualizaciones manualmente, use [`SYSTEM STOP|START|REFRESH|WAIT|CANCEL VIEW`](/es/reference/statements/system#managing-refreshable-materialized-views).

Para esperar a que se complete una actualización, use [`SYSTEM WAIT VIEW`](/es/reference/statements/system#wait-view). En particular, resulta útil para esperar a que termine la actualización inicial tras crear una vista.

<Note>
  Dato curioso: la consulta de actualización puede leer de la vista que se está actualizando y ver la versión de los datos anterior a la actualización. Esto significa que puede implementar el juego de la vida de Conway: [https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==](https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==)
</Note>

<div id="window-view">
  ## Window View
</div>

<Info>
  Esta es una función experimental que puede cambiar de forma incompatible con versiones anteriores en futuras versiones. Habilite el uso de las Window View y de la consulta `WATCH` mediante la opción de configuración [allow\_experimental\_window\_view](/es/reference/settings/session-settings#allow_experimental_window_view). Introduzca el comando `set allow_experimental_window_view = 1`.
</Info>

```sql theme={null}
CREATE WINDOW VIEW [IF NOT EXISTS] [db.]table_name [TO [db.]table_name] [INNER ENGINE engine] [ENGINE engine] [WATERMARK strategy] [ALLOWED_LATENESS interval_function] [POPULATE]
AS SELECT ...
GROUP BY time_window_function
[COMMENT 'comment']
```

Una window view puede agregar datos por ventana de tiempo y generar los resultados cuando la ventana esté lista para dispararse. Almacena los resultados parciales de la agregación en una tabla interna (o especificada) para reducir la latencia, y puede enviar el resultado del procesamiento a una tabla especificada o enviar notificaciones mediante la consulta WATCH.

Crear una window view es similar a crear `MATERIALIZED VIEW`. Una window view necesita un motor de almacenamiento interno para guardar datos intermedios. El almacenamiento interno puede especificarse mediante la cláusula `INNER ENGINE`; la window view usará `AggregatingMergeTree` como motor interno predeterminado.

Al crear una window view sin `TO [db].[table]`, debe especificar `ENGINE`, el motor de tabla para almacenar los datos.

<div id="time-window-functions">
  ### Funciones de ventana de tiempo
</div>

Las [funciones de ventana de tiempo](/es/reference/functions/regular-functions/time-window-functions) se utilizan para obtener los límites inferior y superior de la ventana de los registros. La window view debe usarse con una función de ventana de tiempo.

<div id="time-attributes">
  ### ATRIBUTOS DE TIEMPO
</div>

Window view admite el uso de **tiempo de procesamiento** y **tiempo de evento**.

El **tiempo de procesamiento** permite que window view genere resultados en función de la hora de la máquina local y se usa de forma predeterminada. Es la noción de tiempo más sencilla, pero no proporciona determinismo. El atributo de tiempo de procesamiento puede definirse estableciendo el valor de `time_attr` de la función de ventana de tiempo en una columna de la tabla o mediante la función `now()`. La siguiente consulta crea una window view con tiempo de procesamiento.

```sql theme={null}
CREATE WINDOW VIEW wv AS SELECT count(number), tumbleStart(w_id) as w_start from date GROUP BY tumble(now(), INTERVAL '5' SECOND) as w_id
```

El **tiempo del evento** es el momento en que ocurrió cada evento individual en el dispositivo que lo produjo. Este tiempo suele estar incluido en los registros cuando se generan. El procesamiento por tiempo del evento permite obtener resultados coherentes incluso en caso de eventos desordenados o tardíos. Window view admite el procesamiento por tiempo del evento mediante la sintaxis `WATERMARK`.

Window view proporciona tres estrategias de watermark:

* `STRICTLY_ASCENDING`: Emite un watermark con la marca temporal máxima observada hasta el momento. Las filas con una marca temporal inferior a la marca temporal máxima no se consideran tardías.
* `ASCENDING`: Emite un watermark con la marca temporal máxima observada hasta el momento menos 1. Las filas con una marca temporal igual o inferior a la marca temporal máxima no se consideran tardías.
* `BOUNDED`: WATERMARK=INTERVAL. Emite watermarks que corresponden a la marca temporal máxima observada menos el retraso especificado.

Las siguientes consultas son ejemplos de creación de una window view con `WATERMARK`:

```sql theme={null}
CREATE WINDOW VIEW wv WATERMARK=STRICTLY_ASCENDING AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
CREATE WINDOW VIEW wv WATERMARK=ASCENDING AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
CREATE WINDOW VIEW wv WATERMARK=INTERVAL '3' SECOND AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
```

De forma predeterminada, la ventana se activará cuando llegue la watermark, y los elementos que lleguen por detrás de la watermark se descartarán. La window view admite el procesamiento de eventos tardíos configurando `ALLOWED_LATENESS=INTERVAL`. Un ejemplo de gestión de la tardanza es:

```sql theme={null}
CREATE WINDOW VIEW test.wv TO test.dst WATERMARK=ASCENDING ALLOWED_LATENESS=INTERVAL '2' SECOND AS SELECT count(a) AS count, tumbleEnd(wid) AS w_end FROM test.mt GROUP BY tumble(timestamp, INTERVAL '5' SECOND) AS wid;
```

Tenga en cuenta que los elementos emitidos por una activación tardía deben tratarse como resultados actualizados de un cálculo anterior. En lugar de activarse al final de las ventanas, la window view se activará inmediatamente cuando llegue el evento tardío. Por lo tanto, generará múltiples salidas para la misma ventana. Los usuarios deben tener en cuenta estos resultados duplicados o deduplicarlos.

Puede modificar la consulta `SELECT` especificada en la window view mediante la sentencia `ALTER TABLE ... MODIFY QUERY`. La estructura de datos resultante de la nueva consulta `SELECT` debe ser la misma que la de la consulta `SELECT` original, con o sin la cláusula `TO [db.]name`. Tenga en cuenta que los datos de la ventana actual se perderán porque el estado intermedio no se puede reutilizar.

<div id="monitoring-new-windows">
  ### Supervisión de nuevas ventanas
</div>

Window view admite la consulta [WATCH](/es/reference/statements/watch) para supervisar los cambios, o use la sintaxis `TO` para enviar los resultados a una tabla.

```sql theme={null}
WATCH [db.]window_view
[EVENTS]
[LIMIT n]
[FORMAT format]
```

Se puede especificar un `LIMIT` para definir el número de actualizaciones que se recibirán antes de finalizar la consulta. La cláusula `EVENTS` puede usarse para obtener una forma abreviada de la consulta `WATCH`, donde, en lugar del resultado de la consulta, solo se obtiene la watermark más reciente de la consulta.

<div id="settings-1">
  ### Configuración
</div>

* `window_view_clean_interval`: El intervalo de limpieza de window view, en segundos, para liberar datos obsoletos. El sistema conservará las ventanas que no se hayan activado por completo según la hora del sistema o la configuración de `WATERMARK`, y eliminará el resto de los datos.
* `window_view_heartbeat_interval`: El intervalo de heartbeat, en segundos, para indicar que la consulta watch sigue activa.
* `wait_for_window_view_fire_signal_timeout`: Tiempo de espera para recibir la señal de activación de window view durante el procesamiento por tiempo de evento.

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

Supongamos que necesitamos contar la cantidad de logs de clics por cada 10 segundos en una tabla de logs llamada `data`, cuya estructura es:

```sql theme={null}
CREATE TABLE data ( `id` UInt64, `timestamp` DateTime) ENGINE = Memory;
```

Primero, creamos una window view con una tumble window con un intervalo de 10 segundos:

```sql theme={null}
CREATE WINDOW VIEW wv as select count(id), tumbleStart(w_id) as window_start from data group by tumble(timestamp, INTERVAL '10' SECOND) as w_id
```

A continuación, usamos la consulta `WATCH` para obtener los resultados.

```sql theme={null}
WATCH wv
```

Cuando se insertan logs en la tabla `data`,

```sql theme={null}
INSERT INTO data VALUES(1,now())
```

La consulta `WATCH` debería mostrar los resultados de la siguiente manera:

```text theme={null}
┌─count(id)─┬────────window_start─┐
│         1 │ 2020-01-14 16:56:40 │
└───────────┴─────────────────────┘
```

Como alternativa, podemos adjuntar la salida a otra tabla mediante la sintaxis `TO`.

```sql theme={null}
CREATE WINDOW VIEW wv TO dst AS SELECT count(id), tumbleStart(w_id) as window_start FROM data GROUP BY tumble(timestamp, INTERVAL '10' SECOND) as w_id
```

Se pueden encontrar ejemplos adicionales en las pruebas con estado de ClickHouse (allí se llaman `*window_view*`).

<div id="window-view-usage">
  ### Uso de Window View
</div>

La window view es útil en los siguientes escenarios:

* **Monitoreo**: Agrega y calcula las métricas de los logs a lo largo del tiempo, y envía los resultados a una tabla de destino. El dashboard puede usar la tabla de destino como tabla de origen.
* **Análisis**: Agrega y preprocesa automáticamente los datos dentro de la ventana de tiempo. Esto puede ser útil al analizar una gran cantidad de logs. El preprocesamiento elimina cálculos repetidos en múltiples consultas y reduce la latencia de las consultas.

<div id="related-content">
  ## Contenido relacionado
</div>

* Blog: [Cómo trabajar con datos de series temporales en ClickHouse](https://clickhouse.com/blog/working-with-time-series-data-and-functions-ClickHouse)
* Blog: [Creación de una solución de observabilidad con ClickHouse - Parte 2 - Trazas](https://clickhouse.com/blog/storing-traces-and-spans-open-telemetry-in-clickhouse)

<div id="temporary-views">
  ## Vistas temporales
</div>

ClickHouse admite **vistas temporales** con las siguientes características (en línea con las tablas temporales, cuando corresponde):

* **Duración de la sesión**
  Una vista temporal existe solo durante la sesión actual. Se elimina automáticamente cuando la sesión finaliza.

* **Sin base de datos**
  **No se puede** calificar una vista temporal con un nombre de base de datos. Existe fuera de las bases de datos (en el espacio de nombres de la sesión).

* **No replicadas / sin ON CLUSTER**
  Los objetos temporales son locales a la sesión y **no pueden** crearse con `ON CLUSTER`.

* **Resolución de nombres**
  Si un objeto temporal (tabla o vista) tiene el mismo nombre que un objeto persistente y una consulta hace referencia a ese nombre **sin** una base de datos, se usa el objeto **temporal**.

* **Objeto lógico (sin almacenamiento)**
  Una vista temporal solo almacena su texto `SELECT` (usa internamente el motor `View`). No conserva datos y no admite `INSERT`.

* **Cláusula ENGINE**
  **No** es necesario especificar `ENGINE`; si se indica como `ENGINE = View`, se ignora o se trata como la misma vista lógica.

* **Seguridad / privilegios**
  Para crear una vista temporal se requiere el privilegio `CREATE TEMPORARY VIEW`, que se concede implícitamente mediante `CREATE VIEW`.

* **SHOW CREATE**
  Use `SHOW CREATE TEMPORARY VIEW view_name;` para mostrar el DDL de una vista temporal.

<div id="temporary-views-syntax">
  ### Sintaxis
</div>

```sql theme={null}
CREATE TEMPORARY VIEW [IF NOT EXISTS] view_name AS <select_query>
```

`OR REPLACE` **no** se admite para las vistas temporales (para mantener la coherencia con las tablas temporales). Si necesita “reemplazar” una vista temporal, elimínela y vuelva a crearla.

<div id="examples">
  ### Ejemplos
</div>

Cree una tabla fuente temporal y una vista temporal sobre esta:

```sql theme={null}
CREATE TEMPORARY TABLE t_src (id UInt32, val String);
INSERT INTO t_src VALUES (1, 'a'), (2, 'b');

CREATE TEMPORARY VIEW tview AS
SELECT id, upper(val) AS u
FROM t_src
WHERE id <= 2;

SELECT * FROM tview ORDER BY id;
```

Muestra su DDL:

```sql theme={null}
SHOW CREATE TEMPORARY VIEW tview;
```

Elimínela:

```sql theme={null}
DROP TEMPORARY VIEW IF EXISTS tview;  -- las vistas temporales se eliminan con la sintaxis TEMPORARY TABLE
```

<div id="temporary-views-limitations">
  ### No permitidos / limitaciones
</div>

* `CREATE OR REPLACE TEMPORARY VIEW ...` → **no permitido** (usa `DROP` + `CREATE`).
* `CREATE TEMPORARY MATERIALIZED VIEW ...` / `WINDOW VIEW` → **no permitido**.
* `CREATE TEMPORARY VIEW db.view AS ...` → **no permitido** (sin calificador de base de datos).
* `CREATE TEMPORARY VIEW view ON CLUSTER 'name' AS ...` → **no permitido** (los objetos temporales son locales a la sesión).
* `POPULATE`, `REFRESH`, `TO [db.table]`, motores internos y todas las cláusulas específicas de las MV → **no aplicables** a las vistas temporales.

<div id="temporary-views-distributed-notes">
  ### Notas sobre las consultas distribuidas
</div>

Una **vista** temporal es solo una definición; no hay datos que transferir. Si la vista temporal hace referencia a **tablas** temporales (p. ej., `Memory`), sus datos pueden enviarse a servidores remotos durante la ejecución de consultas distribuidas, del mismo modo que ocurre con las tablas temporales.

<div id="temporary-views-distributed-example">
  #### Ejemplo
</div>

```sql theme={null}
-- Una tabla en memoria con ámbito de sesión
CREATE TEMPORARY TABLE temp_ids (id UInt64) ENGINE = Memory;

INSERT INTO temp_ids VALUES (1), (5), (42);

-- Una vista con ámbito de sesión sobre la tabla temporal (puramente lógica)
CREATE TEMPORARY VIEW v_ids AS
SELECT id FROM temp_ids;

-- Reemplaza 'test' con el nombre de tu cluster.
-- GLOBAL JOIN obliga a ClickHouse a *enviar* el lado pequeño del join (temp_ids a través de v_ids)
-- a cada servidor remoto que ejecuta el lado izquierdo.
SELECT count()
FROM cluster('test', system.numbers) AS n
GLOBAL ANY INNER JOIN v_ids USING (id)
WHERE n.number < 100;

```
