Composable semantic views¶
What are composable semantic views?¶
Composable semantic views introduce an IMPORTS clause that lets one semantic view pull in the full
set of tables, dimensions, facts, metrics, and relationships from another semantic view. This creates a
reusable, shared semantic layer where common business definitions are authored once and referenced by
many downstream views.
Without composability, teams that need the same customer, account, or calendar definitions must duplicate them in every semantic view. When definitions drift apart, queries return inconsistent results and maintenance costs increase. Composable semantic views solve this by establishing a single source of truth.
Use cases¶
-
Shared dimensions: Define customer, account, product, geography, or calendar entities in one base semantic view. Domain teams (sales, marketing, finance) import the base view and add their own local facts and metrics.
-
Centralized governance: Business-critical definitions (revenue, churn, active users) are owned by a central analytics team. Downstream consumers import these definitions and can’t accidentally alter them.
-
Modular semantic layers: Large organizations can decompose a monolithic semantic view into focused modules (one per domain) that compose together, reducing complexity and improving change isolation.
-
Cross-domain queries: A composed view that imports both a customer dimension and an orders domain lets users query revenue by customer segment without writing joins or understanding the physical schema.
SQL syntax¶
CREATE SEMANTIC VIEW with IMPORTS¶
The IMPORTS clause appears before the TABLES clause. You can import one or more semantic views.
A composed view can also omit TABLES entirely if it only combines imported entities.
Key rules:
- Imports are all-or-nothing: when you import a semantic view, all of its entities are brought in. You can’t selectively import individual tables or calculations, and name collisions between imports aren’t merged automatically.
- A composed view can only reference imported calculations (dimensions, facts, metrics). It can’t reference the physical columns of an imported entity directly.
- Imported entities are referenced by their logical table name and calculation name (for example,
customers.d_regionororders.m_total), the same way you reference local objects. - Relationships between imported entities use logical dimension or fact names, not physical column names.
- A composed view can define local tables alongside imports.
- A composed view can define new metrics on imported entities.
Transitive imports¶
Import chains are resolved transitively. If view A imports view B, and view B imports view C, then view A has access to all entities from both B and C:
Runtime behavior¶
A composed view resolves imported objects at query time (late binding). It doesn’t freeze a snapshot of
the source view’s definitions. If the source is altered to remove an object that the composed view
references, the query fails with error 000904 (invalid identifier).
To fix this, restore the missing object in the source view or update the query.
Privilege resolution¶
To create a composed view, the role must have both REFERENCES and SELECT privileges on each directly imported semantic view.
At query time, imported base tables resolve under the source semantic view’s owner role, not the caller’s role. A user can query a composed view without direct access to the underlying base tables, as long as they have the appropriate privileges on the composed view itself.
YAML format¶
Composable semantic views are supported in YAML. Use the imports top-level block to specify
which semantic views to import:
When a composed view defines a local calc on an imported entity, the exported table entry includes
is_imported: true to mark it as a shadow of the imported entity:
The export also includes an imported_semantic_models block containing the full YAML body of every
semantic view in the transitive import closure.
Metadata and introspection¶
DESCRIBE SEMANTIC VIEW¶
DESCRIBE SEMANTIC VIEW exposes composition through additional row types:
- IMPORT rows: One row per directly imported semantic view, with columns
IMPORTED_SEMANTIC_VIEW_DATABASE_NAME,IMPORTED_SEMANTIC_VIEW_SCHEMA_NAME, andIMPORTED_SEMANTIC_VIEW_NAME. - Shadow TABLE rows: Appear when the composed view defines a local calc on an imported entity.
These rows have empty
BASE_TABLE_*values. - Calculations on shadows: Normal METRIC/DIMENSION rows attached to shadow tables.
SHOW SEMANTIC VIEWS¶
The SHOW SEMANTIC VIEWS command includes an imports column that lists direct imports as an array
of fully qualified names. Non-composed views show an empty array ([]).
GET_ DDL¶
GET_DDL output includes the IMPORTS clause with fully qualified semantic view names:
SYSTEM$READ_ YAML_ FROM_ SEMANTIC_ VIEW¶
See YAML format for the full output structure.
Limitations¶
- Cortex Analyst: Cortex Analyst doesn’t support semantic views that use the
IMPORTSclause. Queries sent through Cortex Analyst that reference a composed semantic view will fail. - Snowsight: Snowsight doesn’t support semantic views with imports. Attempting to view or manage a composed semantic view in Snowsight generates an error.
- Replication: Semantic views that use the
IMPORTSclause aren’t replicated. They are skipped during account or database replication. - Imports are all-or-nothing. You can’t selectively import individual tables or calculations from a source view. Name collisions between imported views aren’t merged; they must be resolved before creation.
- A composed view can only reference imported calculations (dimensions, facts, metrics), not the physical columns of imported entities.
- Diamond import graphs (the same source view reachable through multiple paths) aren’t supported.
- Relationships on imported entities must reference logical names (dimensions or facts), not physical column names from the imported base table.
Example: shared account dimension across domains¶
This end-to-end example creates a shared account dimension and imports it into two domain-specific semantic views (sales and marketing), then runs queries that combine imported and local objects.