CREATE MATERIALIZED VIEW statement creates a stored dataset from a query result. Unlike regular queries that execute each time, materialized views persist their results for faster access.
Syntax
Options summary
REFRESH_SCHEDULE
Defines when the materialized view automatically refreshes with new data. Syntax:
CRON format:
For large datasets, consider using Incremental View Maintenance to refresh only changed data.
DISPLAY_NAME
A human-readable name shown in the Narrative I/O interface. Syntax:DESCRIPTION
Documentation text describing the view’s purpose and contents. Syntax:EXPIRE
Sets a data retention policy that determines how long data is kept. Syntax:
ISO 8601 duration format:
P30D- 30 daysP6M- 6 monthsP1Y- 1 yearP1Y6M- 1 year and 6 months
TAGS
Labels for organizing and filtering materialized views. Syntax:WRITE_MODE
Determines how data is written when the view refreshes. Syntax:
When to use each:
- overwrite: Use when you want a complete snapshot of the current state. Good for dashboards and reports where you always want the latest data.
- append: Use when building a historical record. Good for event logs or time-series data where you want to accumulate data over time.
EXTENDED_STATS
Controls whether additional statistics are computed for the dataset. Syntax:
Extended statistics help the query optimizer but increase refresh time. Use
all for frequently queried views and none for large views where refresh speed is critical.
PARTITIONED_BY
Defines how the stored data is partitioned for improved query performance. Syntax:
Partitioning improves query performance when filtering on the partitioned field. Choose a partition scheme that matches your most common query patterns.
MERGE ON
Defines upsert logic that matches incoming rows against existing data during refresh. Use MERGE ON to update existing records and insert new ones without creating duplicates. Syntax:
Example:
Complete example
- Refreshes daily
- Stores female user demographics from the last 160 days
- Partitions data by day for efficient time-based queries
- Retains all historical data indefinitely
- Computes full statistics for query optimization
Output column types
Every column produced by theSELECT must resolve to a type the materialized view store can persist: STRING, BOOLEAN, LONG, DOUBLE, DATE, TIMESTAMP, and nested ARRAY/STRUCT of those types. Types such as DECIMAL, BINARY, INTERVAL, and MAP — as well as intermediate expression results that resolve to them — are not supported as stored output.
Validation rejects unsupported output types before the view is created. /nql/validate, /nql/compile, and /nql/run return a 422 Unsupported Type Error naming the offending column and its type, and nested types report the innermost unsupported type (for example, ARRAY<DECIMAL> points at DECIMAL). CAST the column to a supported type in the SELECT to resolve the error — for example, CAST(price AS DOUBLE) AS price.
Plain
SELECT queries run through /nql/run are not subject to this restriction — the output-type check only applies when the result is being materialized into a stored view.If you need a lightweight query abstraction that re-evaluates at query time instead of storing results, consider using a view dataset instead. View datasets are created through the SDK or API with the
create_as_view option rather than through NQL syntax.Related content
Creating Materialized Views
Step-by-step guide to creating your first materialized view
Incremental Upserts
Use MERGE ON for deduplication and incremental updates
Materialized Views
Understand when and why to use materialized views
Incremental View Maintenance
Learn how NQL optimizes view refreshes

