Skip to main content
The 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:
Values: CRON format:
Example: Refresh every Monday at 3:15 PM UTC:
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:
If not specified, the view name is used as the display name.

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:
Values: ISO 8601 duration format:
  • P30D - 30 days
  • P6M - 6 months
  • P1Y - 1 year
  • P1Y6M - 1 year and 6 months

TAGS

Labels for organizing and filtering materialized views. Syntax:
Tags help categorize views and can be used to filter views in the UI or via API.

WRITE_MODE

Determines how data is written when the view refreshes. Syntax:
Values: 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.
When using append mode, ensure your query includes appropriate filters to avoid inserting duplicate records.

EXTENDED_STATS

Controls whether additional statistics are computed for the dataset. Syntax:
Values: 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:
Transforms: 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:
Auto-generated aliases: Example:
MERGE ON is only valid within CREATE MATERIALIZED VIEW statements. It cannot be used as a standalone command.
For step-by-step guidance and practical examples, see Incremental Upserts with MERGE ON.

Complete example

This example creates a materialized view that:
  • 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 the SELECT 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.

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