mit einem Klick
snowflake-sql
// Snowflake-specific SQL patterns: QUALIFY for window filtering, LATERAL FLATTEN for arrays, semi-structured VARIANT data, ILIKE for case-insensitive matching, date functions, and time travel.
// Snowflake-specific SQL patterns: QUALIFY for window filtering, LATERAL FLATTEN for arrays, semi-structured VARIANT data, ILIKE for case-insensitive matching, date functions, and time travel.
Gather business context from Notion before dbt builds. Searches pages, extracts definitions/decisions/constraints, writes structured context for the build agent and notion-verify subagent.
Load at Step 1 before exploring the project. Covers Notion context gathering, output shape inference, incremental model handling, and what to trust in YML.
Load when dbt run or dbt parse fails. Covers YML duplicate patches, ref errors, passthrough model warnings, current_date fixes, DuckDB error messages, and zero-row diagnosis.
Load at Step 4 when writing SQL models. Covers column naming, type preservation, JOIN defaults, lookup joins, sibling models, materialization, packages, and filtering rules.
Load when hitting DuckDB syntax errors or writing DuckDB-specific SQL. Covers gotchas that differ from PostgreSQL/MySQL.
BigQuery-specific SQL patterns: UNNEST for array expansion, STRUCT, ARRAY_AGG, DATE_DIFF/DATE_ADD, backtick-quoted table references, EXCEPT/REPLACE in SELECT, approximate aggregation, partitioned and wildcard tables.
| name | snowflake-sql |
| description | Snowflake-specific SQL patterns: QUALIFY for window filtering, LATERAL FLATTEN for arrays, semi-structured VARIANT data, ILIKE for case-insensitive matching, date functions, and time travel. |
| type | skill |
Instead of wrapping in a subquery, use QUALIFY:
-- Find the latest record per customer
SELECT customer_id, order_date, amount
FROM orders
QUALIFY ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date DESC) = 1;
-- Top 5 products by sales
SELECT product_id, total_sales
FROM sales_summary
QUALIFY DENSE_RANK() OVER (ORDER BY total_sales DESC) <= 5;
-- Case-insensitive LIKE
WHERE product_name ILIKE '%widget%'
-- Case-insensitive equality
WHERE UPPER(status) = 'ACTIVE'
-- or
WHERE status ILIKE 'active'
-- Explode an ARRAY column
SELECT t.id, f.value AS item
FROM table t,
LATERAL FLATTEN(input => t.array_col) f;
-- Access VARIANT fields
SELECT col:field_name::STRING AS field_value
FROM table;
-- Parse JSON string
SELECT PARSE_JSON(json_col):key::STRING AS val
FROM table;
-- Add/subtract time
DATEADD(day, 7, order_date) -- 7 days from order_date
DATEADD(month, -1, current_date()) -- 1 month ago
-- Difference between dates
DATEDIFF(day, start_date, end_date) -- days between dates
DATEDIFF(month, start_date, end_date)
-- Truncate to period
DATE_TRUNC('month', event_ts)
DATE_TRUNC('year', event_ts)
-- Current timestamp
CURRENT_TIMESTAMP()
CURRENT_DATE()
SPLIT_PART(col, '/', 1) -- split by delimiter, get Nth part
REGEXP_SUBSTR(col, '[0-9]+') -- first match of regex
TRIM(col) -- remove leading/trailing whitespace
LTRIM(col, '0') -- remove leading zeros
UPPER(col) / LOWER(col)
CONCAT(col1, '-', col2) -- or col1 || '-' || col2
-- NULL-safe: TRUE when both are NULL or both equal
col1 IS NOT DISTINCT FROM col2
-- COALESCE for default values
COALESCE(col, 'unknown')
-- Query table as it was 1 hour ago
SELECT * FROM my_table AT (OFFSET => -3600);
-- Query at a specific timestamp
SELECT * FROM my_table AT (TIMESTAMP => '2024-01-01'::TIMESTAMP);
= NULL — use IS NULL<> for NULL comparison — use IS NOT NULLQUALIFY over subquery wrapping for window filterscol:field::STRING"lower_case_col" when column names are lowercase in source. Always check with describe_table.LISTAGG(col, ',') WITHIN GROUP (ORDER BY col) for string aggregation (not GROUP_CONCAT).