Semantic view description quality: a rubric, a linter, and how to apply fixes: code¶
Every file in the Semantic view description quality: a rubric, a linter, and how to apply fixes recipe. To run the recipe, download description-quality.zip, unzip it, and run the scripts from the description-quality/ folder as the recipe describes. Comments in the files that say “see README” refer to the recipe page; the zip includes it as README.md.
sql/¶
sql/01_example_setup.sql¶
-- =============================================================================
-- Semantic view description quality: example setup
-- A small orders table and a semantic view whose descriptions show the common
-- failure modes: missing, circular, padded, vague, and contradicting the SQL.
-- =============================================================================
SET DB = 'COOKBOOK_DESCRIPTION_QUALITY';
SET WH = 'COOKBOOK_DESCRIPTION_QUALITY_WH';
SET ROLE_NAME = 'COOKBOOK_DESCRIPTION_QUALITY_ROLE';
SET CUR_USER = '"' || CURRENT_USER() || '"';
USE ROLE ACCOUNTADMIN;
CREATE ROLE IF NOT EXISTS IDENTIFIER($ROLE_NAME) COMMENT = 'Cortex AI Cookbook: description-quality';
GRANT ROLE IDENTIFIER($ROLE_NAME) TO USER IDENTIFIER($CUR_USER);
GRANT ROLE IDENTIFIER($ROLE_NAME) TO ROLE SYSADMIN;
GRANT DATABASE ROLE SNOWFLAKE.CORTEX_USER TO ROLE IDENTIFIER($ROLE_NAME);
CREATE WAREHOUSE IF NOT EXISTS IDENTIFIER($WH)
WAREHOUSE_SIZE = 'XSMALL' AUTO_SUSPEND = 60 AUTO_RESUME = TRUE INITIALLY_SUSPENDED = TRUE
COMMENT = 'Cortex AI Cookbook: description-quality';
GRANT USAGE, OPERATE ON WAREHOUSE IDENTIFIER($WH) TO ROLE IDENTIFIER($ROLE_NAME);
CREATE DATABASE IF NOT EXISTS IDENTIFIER($DB) COMMENT = 'Cortex AI Cookbook: description-quality';
GRANT OWNERSHIP ON DATABASE IDENTIFIER($DB) TO ROLE IDENTIFIER($ROLE_NAME) COPY CURRENT GRANTS;
USE ROLE IDENTIFIER($ROLE_NAME);
USE WAREHOUSE IDENTIFIER($WH);
USE DATABASE IDENTIFIER($DB);
CREATE SCHEMA IF NOT EXISTS SALES;
USE SCHEMA SALES;
-- Fictional Contoso Outdoor orders. ORD_CHNL is a legacy code: W = web, S = store, P = phone.
CREATE OR REPLACE TABLE ORDERS (
ORDER_ID NUMBER,
CUSTOMER_NAME VARCHAR,
ORDER_DATE DATE,
STATUS VARCHAR,
ORD_CHNL VARCHAR,
GROSS_AMOUNT NUMBER(10,2),
DISCOUNT_AMOUNT NUMBER(10,2),
NET_AMOUNT NUMBER(10,2)
);
INSERT INTO ORDERS
SELECT SEQ4() + 1,
ARRAY_CONSTRUCT('Avery Lin', 'Jordan Blake', 'Sam Ortiz', 'Riley Chen')[MOD(SEQ4(), 4)]::VARCHAR,
DATEADD(day, MOD(SEQ4() * 7, 90), '2026-01-01'::DATE),
ARRAY_CONSTRUCT('SHIPPED', 'SHIPPED', 'RETURNED', 'CANCELLED')[MOD(SEQ4(), 4)]::VARCHAR,
ARRAY_CONSTRUCT('W', 'S', 'P')[MOD(SEQ4(), 3)]::VARCHAR,
100 + MOD(SEQ4() * 37, 400), MOD(SEQ4() * 11, 40), 0
FROM TABLE(GENERATOR(ROWCOUNT => 40));
UPDATE ORDERS SET NET_AMOUNT = GROSS_AMOUNT - DISCOUNT_AMOUNT;
-- The "before" semantic view. Each weak description is typical of first drafts.
CREATE OR ALTER SEMANTIC VIEW ORDERS_SV
TABLES (
orders AS ORDERS PRIMARY KEY (ORDER_ID) COMMENT = 'Orders table'
)
FACTS (
orders.discount_amount AS DISCOUNT_AMOUNT COMMENT = 'Discount',
orders.net_amount AS NET_AMOUNT
)
DIMENSIONS (
orders.customer_name AS CUSTOMER_NAME COMMENT = 'Name of the customer',
orders.order_date AS ORDER_DATE
COMMENT = 'This field represents the date on which the order was placed by the customer in the system and recorded in the database',
orders.status AS STATUS,
orders.ord_chnl AS ORD_CHNL COMMENT = 'Channel'
)
METRICS (
orders.total_revenue AS SUM(net_amount)
WITH SYNONYMS = ('revenue', 'sales', 'income', 'turnover', 'money', 'amount')
COMMENT = 'The total revenue',
orders.avg_order_value AS AVG(net_amount) COMMENT = 'Total value of all orders',
orders.order_count AS COUNT(order_id) COMMENT = 'Orders'
)
COMMENT = 'Orders';
sql/02_lint_descriptions.sql¶
-- =============================================================================
-- Semantic view description quality: lint
-- Part 1 is deterministic: heuristic checks over the INFORMATION_SCHEMA views
-- for semantic views (no model call). Part 2 grades each description with
-- AI_COMPLETE against the four-criteria rubric and proposes a rewrite.
-- Point both at your own view: set DB, SCHEMA_NAME, and SV_NAME to the view, and
-- ROLE_NAME and WH to a role with any privilege on it and a warehouse that role
-- can use. The script reads INFORMATION_SCHEMA only and creates nothing, so the
-- role needs no CREATE privilege in your schema.
-- =============================================================================
SET DB = 'COOKBOOK_DESCRIPTION_QUALITY';
SET SCHEMA_NAME = 'SALES';
SET SV_NAME = 'ORDERS_SV';
SET WH = 'COOKBOOK_DESCRIPTION_QUALITY_WH';
SET ROLE_NAME = 'COOKBOOK_DESCRIPTION_QUALITY_ROLE';
SET MODEL = 'claude-sonnet-4-6';
USE ROLE IDENTIFIER($ROLE_NAME);
USE WAREHOUSE IDENTIFIER($WH);
USE DATABASE IDENTIFIER($DB);
-- Both parts start from the same list: every dimension, fact, and metric of the
-- view with its expression, description, and synonyms (the sv CTE below).
-- -----------------------------------------------------------------------------
-- Part 1: heuristic checks. Each flag is a prompt to look, not a verdict.
-- -----------------------------------------------------------------------------
WITH sv AS (
SELECT 'DIMENSION' AS KIND, SEMANTIC_VIEW_SCHEMA, SEMANTIC_VIEW_NAME, TABLE_NAME, NAME, EXPRESSION, COMMENT, SYNONYMS
FROM INFORMATION_SCHEMA.SEMANTIC_DIMENSIONS
UNION ALL
SELECT 'FACT', SEMANTIC_VIEW_SCHEMA, SEMANTIC_VIEW_NAME, TABLE_NAME, NAME, EXPRESSION, COMMENT, SYNONYMS
FROM INFORMATION_SCHEMA.SEMANTIC_FACTS
UNION ALL
SELECT 'METRIC', SEMANTIC_VIEW_SCHEMA, SEMANTIC_VIEW_NAME, TABLE_NAME, NAME, EXPRESSION, COMMENT, SYNONYMS
FROM INFORMATION_SCHEMA.SEMANTIC_METRICS
),
e AS (
SELECT *,
-- Words in the description that are not in the element name and are not filler.
ARRAY_EXCEPT(
SPLIT(REGEXP_REPLACE(LOWER(COALESCE(COMMENT, '')), '[^a-z0-9 ]', ''), ' '),
ARRAY_CAT(SPLIT(LOWER(NAME), '_'),
['', 'the', 'a', 'an', 'of', 'for', 'in', 'on', 'and', 'or', 'this', 'is', 'field', 'column', 'value'])
) AS NEW_WORDS
FROM sv
WHERE SEMANTIC_VIEW_SCHEMA = $SCHEMA_NAME AND SEMANTIC_VIEW_NAME = $SV_NAME
)
SELECT KIND, NAME, EXPRESSION, COMMENT,
ARRAY_COMPACT(ARRAY_CONSTRUCT(
IFF(NULLIF(TRIM(COMMENT), '') IS NULL, 'MISSING: no description', NULL),
IFF(NULLIF(TRIM(COMMENT), '') IS NOT NULL AND ARRAY_SIZE(NEW_WORDS) = 0,
'CIRCULAR: adds nothing beyond the name', NULL),
IFF(COMMENT ILIKE 'this field%' OR COMMENT ILIKE 'this column%' OR COMMENT ILIKE 'this is the%'
OR COMMENT ILIKE '%in the database%' OR COMMENT ILIKE '%in the system%',
'PADDED: boilerplate phrasing', NULL),
IFF(KIND = 'METRIC' AND EXPRESSION ILIKE 'AVG(%' AND COMMENT ILIKE ANY ('%total%', '%sum%')
AND NOT COMMENT ILIKE ANY ('%average%', '%mean%'),
'CONTRADICTS SQL: says total, expression is AVG', NULL),
IFF(KIND = 'METRIC' AND EXPRESSION ILIKE 'SUM(%' AND COMMENT ILIKE ANY ('%average%', '%mean%'),
'CONTRADICTS SQL: says average, expression is SUM', NULL),
IFF(KIND IN ('METRIC', 'FACT') AND NULLIF(TRIM(COMMENT), '') IS NOT NULL
AND NOT REGEXP_LIKE(COMMENT, '.*(USD|dollar|percent|%|count|number|days|units|currency).*', 'i'),
'UNIT: no unit or type of quantity stated', NULL),
IFF(ARRAY_SIZE(SYNONYMS) > 0, 'SYNONYMS: ' || ARRAY_SIZE(SYNONYMS)::VARCHAR
|| ' synonyms; keep only proprietary or legacy terms', NULL)
)) AS FLAGS
FROM e
ORDER BY ARRAY_SIZE(FLAGS) DESC, KIND, NAME;
-- -----------------------------------------------------------------------------
-- Part 2: model-graded rubric. One AI_COMPLETE call per element; the grade and
-- the rewrite are suggestions for a person to review, not changes.
-- -----------------------------------------------------------------------------
WITH sv AS (
SELECT 'DIMENSION' AS KIND, SEMANTIC_VIEW_SCHEMA, SEMANTIC_VIEW_NAME, TABLE_NAME, NAME, EXPRESSION, COMMENT, SYNONYMS
FROM INFORMATION_SCHEMA.SEMANTIC_DIMENSIONS
UNION ALL
SELECT 'FACT', SEMANTIC_VIEW_SCHEMA, SEMANTIC_VIEW_NAME, TABLE_NAME, NAME, EXPRESSION, COMMENT, SYNONYMS
FROM INFORMATION_SCHEMA.SEMANTIC_FACTS
UNION ALL
SELECT 'METRIC', SEMANTIC_VIEW_SCHEMA, SEMANTIC_VIEW_NAME, TABLE_NAME, NAME, EXPRESSION, COMMENT, SYNONYMS
FROM INFORMATION_SCHEMA.SEMANTIC_METRICS
)
SELECT KIND, NAME, EXPRESSION, COMMENT,
g:preciseness::VARCHAR AS PRECISE,
g:conciseness::VARCHAR AS CONCISE,
g:non_circularity::VARCHAR AS NON_CIRCULAR,
g:correctness::VARCHAR AS CORRECT,
g:issue::VARCHAR AS ISSUE,
g:suggested_description::VARCHAR AS SUGGESTED_DESCRIPTION
FROM (
SELECT e.*,
AI_COMPLETE(
model => $MODEL,
prompt => CONCAT(
'Grade this semantic view ', LOWER(KIND), ' description from A (best) to F (worst) on four criteria. ',
'Preciseness: could it be told apart from similar elements (scope, filters, units, grain)? ',
'Conciseness: does every word add meaning? ',
'Non-circularity: does it say more than the element name? ',
'Correctness: does it match the SQL expression, including the aggregation? ',
'A missing description is F on every criterion. Then write a better description of at most two ',
'sentences, using only facts you can see in the name and expression; write UNKNOWN for business ',
'meaning you cannot infer. Respond in JSON.',
'\nName: ', NAME, '\nKind: ', KIND, '\nExpression: ', EXPRESSION,
'\nDescription: ', COALESCE(COMMENT, '(missing)')),
model_parameters => {'temperature': 0},
response_format => {'type': 'json', 'schema': {'type': 'object', 'properties': {
'preciseness': {'type': 'string', 'enum': ['A', 'B', 'C', 'D', 'F']},
'conciseness': {'type': 'string', 'enum': ['A', 'B', 'C', 'D', 'F']},
'non_circularity': {'type': 'string', 'enum': ['A', 'B', 'C', 'D', 'F']},
'correctness': {'type': 'string', 'enum': ['A', 'B', 'C', 'D', 'F']},
'issue': {'type': 'string'},
'suggested_description': {'type': 'string'}},
'required': ['preciseness', 'conciseness', 'non_circularity', 'correctness', 'issue', 'suggested_description']}}
) AS g
FROM sv e
WHERE SEMANTIC_VIEW_SCHEMA = $SCHEMA_NAME AND SEMANTIC_VIEW_NAME = $SV_NAME
)
ORDER BY KIND, NAME;
sql/03_apply_descriptions.sql¶
-- =============================================================================
-- Semantic view description quality: apply better descriptions
-- Route A (DDL): CREATE OR ALTER SEMANTIC VIEW with the new descriptions.
-- Route B (YAML): SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML with create_or_alter = TRUE.
-- ALTER SEMANTIC VIEW can change only the view-level comment, so element
-- descriptions are changed by redefining the view with one of these routes.
-- The model's suggestions from 02 were a starting point; a person filled in the
-- business meaning the model marked UNKNOWN (status values, channel codes, units).
-- =============================================================================
SET DB = 'COOKBOOK_DESCRIPTION_QUALITY';
SET WH = 'COOKBOOK_DESCRIPTION_QUALITY_WH';
SET ROLE_NAME = 'COOKBOOK_DESCRIPTION_QUALITY_ROLE';
SET SCHEMA_FQ = 'COOKBOOK_DESCRIPTION_QUALITY.SALES';
USE ROLE IDENTIFIER($ROLE_NAME);
USE WAREHOUSE IDENTIFIER($WH);
USE DATABASE IDENTIFIER($DB);
USE SCHEMA SALES;
-- -----------------------------------------------------------------------------
-- Route A: DDL
-- Anything omitted is removed: the six synonyms on total_revenue are gone after
-- this runs. The legacy ORD_CHNL is exposed as order_channel, with the old code
-- kept as the one synonym worth having.
-- -----------------------------------------------------------------------------
CREATE OR ALTER SEMANTIC VIEW ORDERS_SV
TABLES (
orders AS ORDERS PRIMARY KEY (ORDER_ID)
COMMENT = 'One row per customer order placed with Contoso Outdoor, January to March 2026, all statuses.'
)
FACTS (
orders.discount_amount AS DISCOUNT_AMOUNT
COMMENT = 'Discount applied to the order, in USD. NET_AMOUNT = GROSS_AMOUNT - DISCOUNT_AMOUNT.',
orders.net_amount AS NET_AMOUNT
COMMENT = 'Order amount after discount, in USD. Excludes tax and shipping.'
)
DIMENSIONS (
orders.customer_name AS CUSTOMER_NAME
COMMENT = 'Full name of the person who placed the order, as entered at checkout.',
orders.order_date AS ORDER_DATE
COMMENT = 'Date the order was placed.',
orders.status AS STATUS
COMMENT = 'Fulfillment status. SHIPPED orders count as sales; RETURNED and CANCELLED orders do not.'
SAMPLE_VALUES ('SHIPPED', 'RETURNED', 'CANCELLED')
IS_ENUM,
orders.order_channel AS CASE ORD_CHNL WHEN 'W' THEN 'Web' WHEN 'S' THEN 'Store' WHEN 'P' THEN 'Phone' END
WITH SYNONYMS = ('ord_chnl')
COMMENT = 'Channel the order came through, decoded from the legacy ORD_CHNL code (W, S, P).'
SAMPLE_VALUES ('Web', 'Store', 'Phone')
IS_ENUM
)
METRICS (
orders.total_revenue AS SUM(net_amount)
COMMENT = 'Sum of NET_AMOUNT in USD across all order statuses. Filter STATUS = SHIPPED for recognized sales.',
orders.avg_order_value AS AVG(net_amount)
COMMENT = 'Average NET_AMOUNT per order, in USD, across all order statuses.',
orders.order_count AS COUNT(order_id)
COMMENT = 'Number of orders, across all statuses.'
)
COMMENT = 'Contoso Outdoor orders with net revenue, discounts, status, and channel.';
-- Re-run Part 1 of 02_lint_descriptions.sql: the only remaining flag is the
-- ord_chnl synonym, which is kept on purpose because it is a legacy code.
-- -----------------------------------------------------------------------------
-- Route B: YAML. Export the current definition, edit descriptions, and apply it:
-- SELECT SYSTEM$READ_YAML_FROM_SEMANTIC_VIEW('COOKBOOK_DESCRIPTION_QUALITY.SALES.ORDERS_SV');
-- Arguments: schema, yaml, verify_only, create_or_alter. TRUE as the third
-- argument validates without creating; FALSE applies it.
-- Applying has the same rule as Route A: an element missing from the YAML is
-- removed from the view. The YAML below is the complete view, element for
-- element the same as Route A (four dimensions, two facts, three metrics), so
-- setting the third argument to FALSE keeps all nine. Edit an export of your own
-- view, never a partial file.
-- -----------------------------------------------------------------------------
CALL SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML($SCHEMA_FQ, $$
name: ORDERS_SV
description: Contoso Outdoor orders with net revenue, discounts, status, and channel.
tables:
- name: ORDERS
description: One row per customer order placed with Contoso Outdoor, January to March 2026, all statuses.
base_table:
database: COOKBOOK_DESCRIPTION_QUALITY
schema: SALES
table: ORDERS
primary_key:
columns: [ORDER_ID]
dimensions:
- name: CUSTOMER_NAME
expr: CUSTOMER_NAME
data_type: VARCHAR
description: Full name of the person who placed the order, as entered at checkout.
- name: STATUS
expr: STATUS
data_type: VARCHAR
description: Fulfillment status. SHIPPED orders count as sales; RETURNED and CANCELLED orders do not.
sample_values: [SHIPPED, RETURNED, CANCELLED]
is_enum: true
- name: ORDER_CHANNEL
expr: CASE ORD_CHNL WHEN 'W' THEN 'Web' WHEN 'S' THEN 'Store' WHEN 'P' THEN 'Phone' END
data_type: VARCHAR
synonyms: [ord_chnl]
description: Channel the order came through, decoded from the legacy ORD_CHNL code (W, S, P).
sample_values: [Web, Store, Phone]
is_enum: true
time_dimensions:
- name: ORDER_DATE
expr: ORDER_DATE
data_type: DATE
description: Date the order was placed.
facts:
- name: DISCOUNT_AMOUNT
expr: DISCOUNT_AMOUNT
data_type: NUMBER(10,2)
description: Discount applied to the order, in USD. NET_AMOUNT = GROSS_AMOUNT - DISCOUNT_AMOUNT.
- name: NET_AMOUNT
expr: NET_AMOUNT
data_type: NUMBER(10,2)
description: Order amount after discount, in USD. Excludes tax and shipping.
metrics:
- name: TOTAL_REVENUE
expr: SUM(orders.net_amount)
description: Sum of NET_AMOUNT in USD across all order statuses. Filter STATUS = SHIPPED for recognized sales.
- name: AVG_ORDER_VALUE
expr: AVG(orders.net_amount)
description: Average NET_AMOUNT per order, in USD, across all order statuses.
- name: ORDER_COUNT
expr: COUNT(orders.order_id)
description: Number of orders, across all statuses.
$$, TRUE, TRUE);
sql/99_teardown.sql¶
-- =============================================================================
-- Semantic view description quality: teardown
-- =============================================================================
SET DB = 'COOKBOOK_DESCRIPTION_QUALITY';
SET WH = 'COOKBOOK_DESCRIPTION_QUALITY_WH';
SET ROLE_NAME = 'COOKBOOK_DESCRIPTION_QUALITY_ROLE';
USE ROLE ACCOUNTADMIN;
DROP DATABASE IF EXISTS IDENTIFIER($DB);
DROP WAREHOUSE IF EXISTS IDENTIFIER($WH);
DROP ROLE IF EXISTS IDENTIFIER($ROLE_NAME);
SHOW DATABASES LIKE 'COOKBOOK_DESCRIPTION_QUALITY%';
SHOW WAREHOUSES LIKE 'COOKBOOK_DESCRIPTION_QUALITY%';
SHOW ROLES LIKE 'COOKBOOK_DESCRIPTION_QUALITY%';