ClickZetta Semantic View
A Semantic View is a schema-level logical data model in ClickZetta Lakehouse. It encapsulates multi-table relationships, dimensions, and metrics into a business semantic layer so that the whole organization queries consistent, reusable definitions instead of re-writing JOINs and metric logic every time.
- For analysis: business users query cross-table data with business terms — no manual JOIN or GROUP BY.
- For governance: metric definitions are managed centrally, avoiding "same metric name, different numbers".
Reference docs (read on demand):
- references/semantic-view-reference.md — complete CREATE / query / management syntax.
- references/metrics-and-modeling.md — advanced metrics (conditional, arithmetic, derived, window, FACTS, PRIVATE), relationship modeling and aggregation grain, NULL handling.
- references/capabilities-limits.md — capability/limit table, troubleshooting by symptom, advanced queries (subquery/CTE/JOIN/CTAS), AI integration.
When to use a semantic view
Modeling has a cost — it is not always the right tool.
| Your situation |
Better choice |
| One-off ad-hoc query, thrown away after use |
Plain SQL |
| Just wrap a complex SQL for reuse, no shared metric definitions |
Normal view |
| Just transparently accelerate an existing query |
Materialized view / Dynamic Table |
| Many people/reports reuse the same metrics and definitions must stay consistent |
Semantic view |
| Let business users query cross-table data in business terms without JOINs |
Semantic view |
Rule of thumb: build a semantic view when the payoff of consistent definitions and repeated reuse outweighs the modeling cost.
Core components
| Component |
Keyword |
Description |
| Logical tables |
TABLES |
Map physical tables, declare PRIMARY/FOREIGN keys; the engine handles JOINs automatically |
| Facts |
FACTS |
Pass a child-table column through as a logical fact so a parent-table metric can aggregate it (cross-table modeling) |
| Dimensions |
DIMENSIONS |
Categorical attributes (who/what/where/when); support computed expressions like YEAR(hire_date) |
| Metrics |
METRICS |
Aggregate measures — general aggregates, conditional (FILTER (WHERE ...)), arithmetic, same-table derived, and window metrics |
| Variables |
VARIABLES |
Named query parameters with default values — dimension/metric expressions reference them, bound at query time so one view serves multiple thresholds/definitions |
Any dimension / metric / fact can be prefixed with PRIVATE to hide it from direct query — it can only be composed into other PUBLIC objects (encapsulate intermediate calculations).
Creating a semantic view
CREATE [ OR REPLACE ] SEMANTIC VIEW [ IF NOT EXISTS ] <view_name>
TABLES (
<table_alias> AS <schema>.<physical_table>
PRIMARY KEY ( <column> [ , ... ] )
[ FOREIGN KEY ( <column> ) REFERENCES <other_alias> [ ( <ref_column> ) ] ]
[ WITH SYNONYMS ( '<synonym>' [ , ... ] ) ]
[ COMMENT = '<description>' ]
[ , ... ]
)
[ RELATIONSHIPS (
<ref_alias> ( <fk_column> [ , ... ] ) REFERENCES <referenced_alias> [ ( <ref_column> [ , ... ] ) ]
[ , ... ]
) ]
[ VARIABLES (
<var_name> <data_type> [ { DEFAULT | = } <default_value> ] [ COMMENT = '<description>' ]
[ , ... ]
) ]
[ FACTS (
[ PRIVATE ] <alias>.<fact_name> AS { <column_expr> | <aggregate_expr> }
[ , ... ]
) ]
[ DIMENSIONS (
[ PRIVATE ] { <alias>.<dim_name> | <dim_name> } AS <expression>
[ WITH SYNONYMS = ( '<synonym>' [ , ... ] ) ]
[ is_unique = { true | false } ] [ is_time = { true | false } ]
[ enum_values = [ <v1>, <v2>, ... ] ]
[ COMMENT = '<description>' ]
[ , ... ]
) ]
[ METRICS (
[ PRIVATE ] <alias>.<metric_name> AS <aggregate_expression>
[ COMMENT = '<description>' ]
[ , ... ]
) ]
[ COMMENT = '<view_description>' ];
⚠️ Clause order is fixed: TABLES → RELATIONSHIPS → VARIABLES → FACTS → DIMENSIONS → METRICS. Only TABLES is required; the rest are optional. An out-of-order clause raises Syntax error at or near '<clause>' (e.g. VARIABLES before RELATIONSHIPS, or FACTS after DIMENSIONS). Dimension metadata order is also fixed: WITH SYNONYMS must come before is_unique/is_time/enum_values.
Foreign keys have two equivalent forms: the inline FOREIGN KEY inside a logical table, or the top-level RELATIONSHIPS clause. Both are accepted on create; SHOW CREATE SEMANTIC VIEW / DESC EXTENDED always read them back normalized as a RELATIONSHIPS clause. CREATE ... IF NOT EXISTS silently skips when the view exists (mutually exclusive with OR REPLACE).
Complete example
DROP SEMANTIC VIEW IF EXISTS doc_test.emp_dept_analysis;
CREATE SEMANTIC VIEW doc_test.emp_dept_analysis
TABLES (
depts AS doc_test.departments
PRIMARY KEY (dept_name),
emps AS doc_test.employees
PRIMARY KEY (id)
FOREIGN KEY (dept) REFERENCES depts (dept_name)
)
DIMENSIONS (
emps.employee_name AS emps.name
WITH SYNONYMS = ('staff name')
is_unique = true
COMMENT = 'Employee name',
emps.department AS emps.dept
COMMENT = 'Department',
emps.hire_year AS YEAR(emps.hire_date)
is_time = true
COMMENT = 'Hire year',
depts.manager_name AS depts.manager
COMMENT = 'Department manager'
)
METRICS (
emps.total_employees AS COUNT(emps.id)
COMMENT = 'Employee count',
emps.avg_salary AS AVG(emps.salary)
COMMENT = 'Average salary',
emps.max_salary AS MAX(emps.salary)
COMMENT = 'Max salary'
)
COMMENT = 'Employee & department analysis';
Notes:
FOREIGN KEY (dept) REFERENCES depts (dept_name) — when the FK column name differs from the referenced primary key, name the referenced column explicitly. FK and referenced column types must match, or CREATE fails.
hire_year is a computed dimension derived from a date via YEAR().
- The table referenced by a foreign key must be defined before the referencing table in
TABLES.
Metric capabilities (brief)
Metrics are standard aggregate expressions — far beyond COUNT/SUM/AVG/MIN/MAX:
METRICS (
-- Conditional (segmented KPI): each FILTER is independent
orders.open_revenue AS SUM(o_totalprice) FILTER (WHERE o_status = 'O'),
-- Arithmetic expression
emps.salary_range AS MAX(salary) - MIN(salary),
-- Same-table derived (reference other named metrics)
emps.total_salary AS SUM(salary),
emps.headcount AS COUNT(id),
emps.avg_salary AS emps.total_salary / emps.headcount,
-- Window (share/running total/rank); PARTITION BY must use a dimension's qualified alias
orders.pct_of_region AS SUM(o_totalprice) * 100.0
/ SUM(SUM(o_totalprice)) OVER (PARTITION BY orders.region)
)
Also supported: COUNT(DISTINCT ...), APPROX_COUNT_DISTINCT, STDDEV, VARIANCE, MEDIAN, PERCENTILE, GROUP_CONCAT, etc. Cross-table metric division (referencing an unrelated table's columns) is not supported — do that in the outer SQL. Full rules and verified outputs: references/metrics-and-modeling.md.
Querying a semantic view
Use the semantic_view() table function — the engine auto-JOINs by foreign keys and groups by the requested dimensions:
SELECT * FROM semantic_view(
<view_name>
[ DIMENSIONS <name> [ , <name> ... ] ]
[ METRICS <name> [ , <name> ... ] ]
[ FACTS <name> [ , <name> ... ] ]
[ WHERE <predicate> ]
[ VARIABLES <var_name> => <value> [ , ... ] ]
);
⚠️ No comma after the view name — the first clause keyword follows directly. DIMENSIONS/METRICS/FACTS may each appear at most once; list multiple items under one keyword separated by commas (DIMENSIONS a, b, not DIMENSIONS a DIMENSIONS b). A comma after the view name or a repeated keyword raises a syntax error (duplicate METRICS clause in semantic_view(); each of DIMENSIONS, METRICS and FACTS may appear at most once).
-- Group metrics by dimension
SELECT * FROM semantic_view(
doc_test.emp_dept_analysis
DIMENSIONS emps.department
METRICS emps.total_employees, emps.avg_salary
);
-- Cross-table dimension (auto JOIN) — group by the manager from depts
SELECT * FROM semantic_view(
doc_test.emp_dept_analysis
DIMENSIONS depts.manager_name
METRICS emps.avg_salary
);
-- Short names (alias prefix optional when unique)
SELECT * FROM semantic_view(
doc_test.emp_dept_analysis
DIMENSIONS department
METRICS total_employees
);
-- Filtering: an inner trailing WHERE, or an outer WHERE — both work
SELECT * FROM semantic_view(
doc_test.emp_dept_analysis
DIMENSIONS emps.department
METRICS emps.avg_salary
) WHERE department = 'Engineering';
- Must specify at least one
DIMENSIONS, METRICS, or FACTS, or you get table or view not found - semantic_view.
DIMENSIONS/METRICS/FACTS are order-independent (METRICS ... DIMENSIONS ... equals DIMENSIONS ... METRICS ...); output columns follow item write order. WHERE and VARIABLES are trailing clauses, after the three keywords, with WHERE before VARIABLES.
- Only
METRICS → single-row global aggregate. Only DIMENSIONS → deduplicated dimension list.
- Filter dimensions with an inner trailing
WHERE or an outer WHERE; ORDER BY / LIMIT and SELECT col1, col2 only go on the outer query.
- Neither WHERE takes a physical column name — use the dimension. The inner
WHERE accepts a qualified alias (emps.department) or short name (department); the outer WHERE references output columns, so short name only (emps.department there raises cannot resolve column).
- Inner
WHERE runs before metric aggregation, so it cannot reference a metric — WHERE total_employees > 1 raises a METRIC '...' is not allowed in the semantic_view() WHERE clause. Filter on aggregates in an outer query: SELECT * FROM (SELECT * FROM semantic_view(...)) t WHERE t.total_employees > 1.
Traditional SQL vs semantic view
-- Traditional (manual JOIN + GROUP BY)
SELECT e.dept, d.manager AS manager_name, COUNT(e.id), AVG(e.salary)
FROM doc_test.employees e
JOIN doc_test.departments d ON e.dept = d.dept_name
GROUP BY e.dept, d.manager;
-- Semantic view (JOIN + aggregation automatic, grain-correct)
SELECT * FROM semantic_view(
doc_test.emp_dept_analysis
DIMENSIONS emps.department, depts.manager_name
METRICS emps.total_employees, emps.avg_salary
);
Grain matters: query grain is driven by the metric's table. Orphan child rows appear with a NULL dimension; dimension members with no fact rows do not appear. Metrics from two sibling one-to-many branches (chasm-trap fan-out) can be combined in one query — the engine aggregates each branch at its own grain and aligns on the dimension, without inflating. See references/metrics-and-modeling.md.
Managing a semantic view
| Command |
Purpose |
CREATE OR REPLACE SEMANTIC VIEW ... |
Atomically replace a definition (use this to change structure) |
SHOW CREATE SEMANTIC VIEW <name> |
Read back the full, replayable CREATE DDL |
DROP SEMANTIC VIEW IF EXISTS <name> |
Drop a view |
ALTER SEMANTIC VIEW <name> RENAME TO <new_name> |
Rename (new name cannot carry a schema prefix) |
ALTER SEMANTIC VIEW <name> SET PROPERTIES ('k'='v') |
Set custom properties (merge/upsert semantics) |
ALTER SEMANTIC VIEW <name> UNSET PROPERTIES ('k') |
Remove a property |
SHOW SEMANTIC VIEWS [ IN <schema> ] |
List views (returns schema_name, table_name) |
DESC EXTENDED <name> |
View full structure — must include EXTENDED |
SHOW SEMANTIC DIMENSIONS / METRICS / FACTS IN <name> |
Structured, one-row-per-object introspection (incl. access = PUBLIC/PRIVATE) |
SHOW SEMANTIC RELATIONSHIPS IN <name> |
Foreign-key relationships, one row each (incl. relationship_type, e.g. MANY_TO_ONE) |
SHOW SEMANTIC TABLES IN <name> |
Logical-to-physical table mapping (incl. base_table, primary_key) |
GRANT / REVOKE SELECT ON SEMANTIC VIEW <name> ... |
Read-only permissions (no INSERT/UPDATE/DELETE) |
ALTER cannot add/drop dimensions or metrics — use CREATE OR REPLACE to replay the full definition (recommended: SHOW CREATE → edit → CREATE OR REPLACE).
- Semantic views are not in
information_schema.tables; use SHOW SEMANTIC VIEWS and DESC EXTENDED.
SHOW SEMANTIC VIEWS does not support LIKE, and has no global cross-schema listing.
Important notes
- No
FILTERS clause: named filters were removed. To filter, define a conditional metric with FILTER (WHERE ...), or use an outer WHERE with a dimension short name.
- TABLES order: a referenced table must be defined before the table whose FK references it.
- FK type match: FK column and referenced column must have the same type, or CREATE raises
type ... does not match.
- Idempotent scripts:
DROP ... IF EXISTS before CREATE, or use CREATE OR REPLACE.
- Metadata is declarative:
is_unique / is_time / enum_values are annotations for AI/metadata tools — they do not affect SQL results, optimization, or value validation. Note DESC EXTENDED reads is_unique/is_time back as true whenever the clause was written at all (value not faithful); synonyms and enum_values read back faithfully.
- Window metrics:
PARTITION BY / ORDER BY must reference a dimension's qualified alias (e.g. orders.region), same-table only, and that dimension must appear in the query's DIMENSIONS.
- PRIVATE objects cannot be queried/filtered directly — only composed into a PUBLIC fact/metric.
- VARIABLES: declared right after
TABLES (before FACTS/DIMENSIONS/METRICS, else Syntax error at or near 'VARIABLES'). Dimension/metric expressions reference a variable by its bare name (no alias. prefix). Bind at query time with semantic_view(... VARIABLES <name> => <value>) (=> or =, constant only); unbound variables use their default. DEFAULT and = are equivalent and both read back as DEFAULT.
1---2name: clickzetta-semantic-view3description: Create, query, and manage ClickZetta Lakehouse Semantic Views — schema-level logical models that encapsulate multi-table JOINs and aggregations into a business-friendly layer of logical tables, dimensions, metrics, and facts. Query with the semantic_view() function without writing JOINs or GROUP BY manually. Triggered when user says "create semantic view", "semantic view", "semantic layer", "define metrics", "define dimensions", "unified metric definitions", "business semantic model", "semantic_view()", "CREATE OR REPLACE SEMANTIC VIEW", "FACTS", "PRIVATE metric", "conditional metric", "window metric", "SHOW SEMANTIC VIEWS", "GRANT SELECT ON SEMANTIC VIEW". Keywords: semantic view, dimension, metric, fact, logical model, unified metrics, semantic layer, grain, chasm trap, FILTER metric4---56# ClickZetta Semantic View78A Semantic View is a **schema-level logical data model** in ClickZetta Lakehouse. It encapsulates multi-table relationships, dimensions, and metrics into a business semantic layer so that the whole organization queries consistent, reusable definitions instead of re-writing JOINs and metric logic every time.910- **For analysis**: business users query cross-table data with business terms — no manual JOIN or GROUP BY.11- **For governance**: metric definitions are managed centrally, avoiding "same metric name, different numbers".1213Reference docs (read on demand):14- [references/semantic-view-reference.md](references/semantic-view-reference.md) — complete CREATE / query / management syntax.15- [references/metrics-and-modeling.md](references/metrics-and-modeling.md) — advanced metrics (conditional, arithmetic, derived, window, FACTS, PRIVATE), relationship modeling and aggregation grain, NULL handling.16- [references/capabilities-limits.md](references/capabilities-limits.md) — capability/limit table, troubleshooting by symptom, advanced queries (subquery/CTE/JOIN/CTAS), AI integration.1718---1920## When to use a semantic view2122Modeling has a cost — it is not always the right tool.2324| Your situation | Better choice |25|---|---|26| One-off ad-hoc query, thrown away after use | Plain SQL |27| Just wrap a complex SQL for reuse, no shared metric definitions | Normal view |28| Just transparently accelerate an existing query | Materialized view / Dynamic Table |29| **Many people/reports reuse the same metrics and definitions must stay consistent** | **Semantic view** |30| **Let business users query cross-table data in business terms without JOINs** | **Semantic view** |3132Rule of thumb: build a semantic view when the payoff of *consistent definitions* and *repeated reuse* outweighs the modeling cost.3334---3536## Core components3738| Component | Keyword | Description |39|---|---|---|40| Logical tables | `TABLES` | Map physical tables, declare PRIMARY/FOREIGN keys; the engine handles JOINs automatically |41| Facts | `FACTS` | Pass a child-table column through as a logical fact so a parent-table metric can aggregate it (cross-table modeling) |42| Dimensions | `DIMENSIONS` | Categorical attributes (who/what/where/when); support computed expressions like `YEAR(hire_date)` |43| Metrics | `METRICS` | Aggregate measures — general aggregates, conditional (`FILTER (WHERE ...)`), arithmetic, same-table derived, and window metrics |44| Variables | `VARIABLES` | Named query parameters with default values — dimension/metric expressions reference them, bound at query time so one view serves multiple thresholds/definitions |4546Any dimension / metric / fact can be prefixed with `PRIVATE` to hide it from direct query — it can only be composed into other `PUBLIC` objects (encapsulate intermediate calculations).4748---4950## Creating a semantic view5152```sql53CREATE [ OR REPLACE ] SEMANTIC VIEW [ IF NOT EXISTS ] <view_name>54TABLES (55 <table_alias> AS <schema>.<physical_table>56 PRIMARY KEY ( <column> [ , ... ] )57 [ FOREIGN KEY ( <column> ) REFERENCES <other_alias> [ ( <ref_column> ) ] ]58 [ WITH SYNONYMS ( '<synonym>' [ , ... ] ) ]59 [ COMMENT = '<description>' ]60 [ , ... ]61)62[ RELATIONSHIPS (63 <ref_alias> ( <fk_column> [ , ... ] ) REFERENCES <referenced_alias> [ ( <ref_column> [ , ... ] ) ]64 [ , ... ]65) ]66[ VARIABLES (67 <var_name> <data_type> [ { DEFAULT | = } <default_value> ] [ COMMENT = '<description>' ]68 [ , ... ]69) ]70[ FACTS (71 [ PRIVATE ] <alias>.<fact_name> AS { <column_expr> | <aggregate_expr> }72 [ , ... ]73) ]74[ DIMENSIONS (75 [ PRIVATE ] { <alias>.<dim_name> | <dim_name> } AS <expression>76 [ WITH SYNONYMS = ( '<synonym>' [ , ... ] ) ]77 [ is_unique = { true | false } ] [ is_time = { true | false } ]78 [ enum_values = [ <v1>, <v2>, ... ] ]79 [ COMMENT = '<description>' ]80 [ , ... ]81) ]82[ METRICS (83 [ PRIVATE ] <alias>.<metric_name> AS <aggregate_expression>84 [ COMMENT = '<description>' ]85 [ , ... ]86) ]87[ COMMENT = '<view_description>' ];88```8990> ⚠️ Clause order is fixed: `TABLES → RELATIONSHIPS → VARIABLES → FACTS → DIMENSIONS → METRICS`. Only `TABLES` is required; the rest are optional. An out-of-order clause raises `Syntax error at or near '<clause>'` (e.g. `VARIABLES` before `RELATIONSHIPS`, or `FACTS` after `DIMENSIONS`). Dimension metadata order is also fixed: `WITH SYNONYMS` must come before `is_unique`/`is_time`/`enum_values`.9192> Foreign keys have two equivalent forms: the inline `FOREIGN KEY` inside a logical table, or the top-level `RELATIONSHIPS` clause. Both are accepted on create; `SHOW CREATE SEMANTIC VIEW` / `DESC EXTENDED` always read them back normalized as a `RELATIONSHIPS` clause. `CREATE ... IF NOT EXISTS` silently skips when the view exists (mutually exclusive with `OR REPLACE`).9394### Complete example9596```sql97DROP SEMANTIC VIEW IF EXISTS doc_test.emp_dept_analysis;98CREATE SEMANTIC VIEW doc_test.emp_dept_analysis99TABLES (100 depts AS doc_test.departments101 PRIMARY KEY (dept_name),102 emps AS doc_test.employees103 PRIMARY KEY (id)104 FOREIGN KEY (dept) REFERENCES depts (dept_name)105)106DIMENSIONS (107 emps.employee_name AS emps.name108 WITH SYNONYMS = ('staff name')109 is_unique = true110 COMMENT = 'Employee name',111 emps.department AS emps.dept112 COMMENT = 'Department',113 emps.hire_year AS YEAR(emps.hire_date)114 is_time = true115 COMMENT = 'Hire year',116 depts.manager_name AS depts.manager117 COMMENT = 'Department manager'118)119METRICS (120 emps.total_employees AS COUNT(emps.id)121 COMMENT = 'Employee count',122 emps.avg_salary AS AVG(emps.salary)123 COMMENT = 'Average salary',124 emps.max_salary AS MAX(emps.salary)125 COMMENT = 'Max salary'126)127COMMENT = 'Employee & department analysis';128```129130Notes:131- `FOREIGN KEY (dept) REFERENCES depts (dept_name)` — when the FK column name differs from the referenced primary key, name the referenced column explicitly. **FK and referenced column types must match**, or CREATE fails.132- `hire_year` is a computed dimension derived from a date via `YEAR()`.133- The table referenced by a foreign key must be defined **before** the referencing table in `TABLES`.134135### Metric capabilities (brief)136137Metrics are standard aggregate expressions — far beyond `COUNT/SUM/AVG/MIN/MAX`:138139```sql140METRICS (141 -- Conditional (segmented KPI): each FILTER is independent142 orders.open_revenue AS SUM(o_totalprice) FILTER (WHERE o_status = 'O'),143 -- Arithmetic expression144 emps.salary_range AS MAX(salary) - MIN(salary),145 -- Same-table derived (reference other named metrics)146 emps.total_salary AS SUM(salary),147 emps.headcount AS COUNT(id),148 emps.avg_salary AS emps.total_salary / emps.headcount,149 -- Window (share/running total/rank); PARTITION BY must use a dimension's qualified alias150 orders.pct_of_region AS SUM(o_totalprice) * 100.0151 / SUM(SUM(o_totalprice)) OVER (PARTITION BY orders.region)152)153```154155Also supported: `COUNT(DISTINCT ...)`, `APPROX_COUNT_DISTINCT`, `STDDEV`, `VARIANCE`, `MEDIAN`, `PERCENTILE`, `GROUP_CONCAT`, etc. Cross-table metric division (referencing an unrelated table's columns) is **not** supported — do that in the outer SQL. Full rules and verified outputs: [references/metrics-and-modeling.md](references/metrics-and-modeling.md).156157---158159## Querying a semantic view160161Use the `semantic_view()` table function — the engine auto-JOINs by foreign keys and groups by the requested dimensions:162163```sql164SELECT * FROM semantic_view(165 <view_name>166 [ DIMENSIONS <name> [ , <name> ... ] ]167 [ METRICS <name> [ , <name> ... ] ]168 [ FACTS <name> [ , <name> ... ] ]169 [ WHERE <predicate> ]170 [ VARIABLES <var_name> => <value> [ , ... ] ]171);172```173174> ⚠️ No comma after the view name — the first clause keyword follows directly. `DIMENSIONS`/`METRICS`/`FACTS` may each appear **at most once**; list multiple items under one keyword separated by commas (`DIMENSIONS a, b`, not `DIMENSIONS a DIMENSIONS b`). A comma after the view name or a repeated keyword raises a syntax error (`duplicate METRICS clause in semantic_view(); each of DIMENSIONS, METRICS and FACTS may appear at most once`).175176```sql177-- Group metrics by dimension178SELECT * FROM semantic_view(179 doc_test.emp_dept_analysis180 DIMENSIONS emps.department181 METRICS emps.total_employees, emps.avg_salary182);183184-- Cross-table dimension (auto JOIN) — group by the manager from depts185SELECT * FROM semantic_view(186 doc_test.emp_dept_analysis187 DIMENSIONS depts.manager_name188 METRICS emps.avg_salary189);190191-- Short names (alias prefix optional when unique)192SELECT * FROM semantic_view(193 doc_test.emp_dept_analysis194 DIMENSIONS department195 METRICS total_employees196);197198-- Filtering: an inner trailing WHERE, or an outer WHERE — both work199SELECT * FROM semantic_view(200 doc_test.emp_dept_analysis201 DIMENSIONS emps.department202 METRICS emps.avg_salary203) WHERE department = 'Engineering';204```205206- Must specify at least one `DIMENSIONS`, `METRICS`, or `FACTS`, or you get `table or view not found - semantic_view`.207- `DIMENSIONS`/`METRICS`/`FACTS` are **order-independent** (`METRICS ... DIMENSIONS ...` equals `DIMENSIONS ... METRICS ...`); output columns follow item write order. `WHERE` and `VARIABLES` are **trailing clauses**, after the three keywords, with `WHERE` before `VARIABLES`.208- Only `METRICS` → single-row global aggregate. Only `DIMENSIONS` → deduplicated dimension list.209- Filter dimensions with an inner trailing `WHERE` or an outer `WHERE`; `ORDER BY` / `LIMIT` and `SELECT col1, col2` only go on the outer query.210- **Neither WHERE takes a physical column name** — use the dimension. The inner `WHERE` accepts a qualified alias (`emps.department`) or short name (`department`); the outer `WHERE` references output columns, so **short name only** (`emps.department` there raises `cannot resolve column`).211- Inner `WHERE` runs **before** metric aggregation, so it cannot reference a metric — `WHERE total_employees > 1` raises `a METRIC '...' is not allowed in the semantic_view() WHERE clause`. Filter on aggregates in an outer query: `SELECT * FROM (SELECT * FROM semantic_view(...)) t WHERE t.total_employees > 1`.212213### Traditional SQL vs semantic view214215```sql216-- Traditional (manual JOIN + GROUP BY)217SELECT e.dept, d.manager AS manager_name, COUNT(e.id), AVG(e.salary)218FROM doc_test.employees e219JOIN doc_test.departments d ON e.dept = d.dept_name220GROUP BY e.dept, d.manager;221222-- Semantic view (JOIN + aggregation automatic, grain-correct)223SELECT * FROM semantic_view(224 doc_test.emp_dept_analysis225 DIMENSIONS emps.department, depts.manager_name226 METRICS emps.total_employees, emps.avg_salary227);228```229230> **Grain matters**: query grain is driven by the metric's table. Orphan child rows appear with a `NULL` dimension; dimension members with no fact rows do not appear. Metrics from two sibling one-to-many branches (chasm-trap fan-out) can be combined in one query — the engine aggregates each branch at its own grain and aligns on the dimension, without inflating. See [references/metrics-and-modeling.md](references/metrics-and-modeling.md).231232---233234## Managing a semantic view235236| Command | Purpose |237|---|---|238| `CREATE OR REPLACE SEMANTIC VIEW ...` | Atomically replace a definition (use this to change structure) |239| `SHOW CREATE SEMANTIC VIEW <name>` | Read back the full, replayable CREATE DDL |240| `DROP SEMANTIC VIEW IF EXISTS <name>` | Drop a view |241| `ALTER SEMANTIC VIEW <name> RENAME TO <new_name>` | Rename (new name cannot carry a schema prefix) |242| `ALTER SEMANTIC VIEW <name> SET PROPERTIES ('k'='v')` | Set custom properties (merge/upsert semantics) |243| `ALTER SEMANTIC VIEW <name> UNSET PROPERTIES ('k')` | Remove a property |244| `SHOW SEMANTIC VIEWS [ IN <schema> ]` | List views (returns `schema_name`, `table_name`) |245| `DESC EXTENDED <name>` | View full structure — **must** include `EXTENDED` |246| `SHOW SEMANTIC DIMENSIONS / METRICS / FACTS IN <name>` | Structured, one-row-per-object introspection (incl. `access` = PUBLIC/PRIVATE) |247| `SHOW SEMANTIC RELATIONSHIPS IN <name>` | Foreign-key relationships, one row each (incl. `relationship_type`, e.g. `MANY_TO_ONE`) |248| `SHOW SEMANTIC TABLES IN <name>` | Logical-to-physical table mapping (incl. `base_table`, `primary_key`) |249| `GRANT / REVOKE SELECT ON SEMANTIC VIEW <name> ...` | Read-only permissions (no INSERT/UPDATE/DELETE) |250251- `ALTER` **cannot** add/drop dimensions or metrics — use `CREATE OR REPLACE` to replay the full definition (recommended: `SHOW CREATE` → edit → `CREATE OR REPLACE`).252- Semantic views are **not** in `information_schema.tables`; use `SHOW SEMANTIC VIEWS` and `DESC EXTENDED`.253- `SHOW SEMANTIC VIEWS` does **not** support `LIKE`, and has no global cross-schema listing.254255---256257## Important notes2582591. **No `FILTERS` clause**: named filters were removed. To filter, define a conditional metric with `FILTER (WHERE ...)`, or use an outer `WHERE` with a dimension short name.2602. **TABLES order**: a referenced table must be defined before the table whose FK references it.2613. **FK type match**: FK column and referenced column must have the same type, or CREATE raises `type ... does not match`.2624. **Idempotent scripts**: `DROP ... IF EXISTS` before `CREATE`, or use `CREATE OR REPLACE`.2635. **Metadata is declarative**: `is_unique` / `is_time` / `enum_values` are annotations for AI/metadata tools — they do **not** affect SQL results, optimization, or value validation. Note `DESC EXTENDED` reads `is_unique`/`is_time` back as `true` whenever the clause was written at all (value not faithful); `synonyms` and `enum_values` read back faithfully.2646. **Window metrics**: `PARTITION BY` / `ORDER BY` must reference a dimension's **qualified alias** (e.g. `orders.region`), same-table only, and that dimension must appear in the query's `DIMENSIONS`.2657. **PRIVATE objects** cannot be queried/filtered directly — only composed into a PUBLIC fact/metric.2668. **VARIABLES**: declared right after `TABLES` (before `FACTS`/`DIMENSIONS`/`METRICS`, else `Syntax error at or near 'VARIABLES'`). Dimension/metric expressions reference a variable by its **bare name** (no `alias.` prefix). Bind at query time with `semantic_view(... VARIABLES <name> => <value>)` (`=>` or `=`, constant only); unbound variables use their default. `DEFAULT` and `=` are equivalent and both read back as `DEFAULT`.267