BigQuery to dbt Model Conversion
Purpose
Transform Google BigQuery DDL (views, tables, stored procedures) into production-quality dbt models
compatible with Snowflake, maintaining the same business logic and data transformation steps while
following dbt best practices.
When to Use This Skill
Activate this skill when users ask about:
- Converting BigQuery views or tables to dbt models
- Migrating BigQuery stored procedures to dbt
- Translating BigQuery SQL syntax to Snowflake
- Generating schema.yml files with tests and documentation
- Handling BigQuery-specific syntax conversions (UNNEST, STRUCT/ARRAY, backtick identifiers)
Task Description
You are a database engineer working for a hospital system. You need to convert BigQuery DDL to
equivalent dbt code compatible with Snowflake, maintaining the same business logic and data
transformation steps while following dbt best practices.
Input Requirements
I will provide you the BigQuery DDL to convert.
Audience
The code will be executed by data engineers who are learning Snowflake and dbt.
Output Requirements
Generate the following:
- One or more dbt models with complete SQL for every column
- A corresponding schema.yml file with appropriate tests and documentation
- A config block with materialization strategy
- Explanation of key changes and architectural decisions
- Inline comments highlighting any syntax that was converted
Conversion Guidelines
General Principles
- Replace procedural logic with declarative SQL where possible
- Break down complex procedures into multiple modular dbt models
- Implement appropriate incremental processing strategies
- Maintain data quality checks through dbt tests
- Use Snowflake SQL functions rather than macros whenever possible
Sample Response Format
-- dbt model: models/[domain]/[target_schema_name]/model_name.sql
{{ config(materialized='view') }}
/* Original Object: [project].[dataset].[object_name]
Source Platform: BigQuery
Purpose: [brief description]
Conversion Notes: [key changes]
Description: [SQL logic description] */
WITH source_data AS (
SELECT
-- INT64 converted to INTEGER
customer_id::INTEGER AS customer_id,
-- STRING converted to VARCHAR
customer_name::VARCHAR(100) AS customer_name,
-- NUMERIC converted to NUMBER
account_balance::NUMBER(18,2) AS account_balance,
-- TIMESTAMP converted to TIMESTAMP_TZ (BigQuery stores UTC)
created_date::TIMESTAMP_TZ AS created_date
FROM {{ ref('upstream_model') }}
),
transformed_data AS (
SELECT
customer_id,
UPPER(customer_name)::VARCHAR(100) AS customer_name_upper,
account_balance,
created_date,
CURRENT_TIMESTAMP()::TIMESTAMP_NTZ AS loaded_at
FROM source_data
)
SELECT
customer_id,
customer_name_upper,
account_balance,
created_date,
loaded_at
FROM transformed_data
## models/[domain]/[target_schema_name]/_models.yml
version: 2
models:
- name: model_name
description: "Table description; converted from BigQuery [Original object name]"
columns:
- name: customer_id
description: "Primary key - unique customer identifier"
tests:
- unique
- not_null
- name: customer_name_upper
description: "Customer name in uppercase"
- name: account_balance
description: "Current account balance; Foreign key to OTHER_TABLE"
tests:
- relationships:
to: ref('OTHER_TABLE')
field: OTHER_TABLE_KEY
- name: created_date
description: "Date the customer record was created"
- name: loaded_at
description: "Timestamp when the record was loaded by dbt"
## dbt_project.yml (excerpt)
models:
my_project:
+materialized: view
domain_name:
+schema: target_schema_name
Specific Translation Rules
dbt Specific Requirements
- If the source is a view, use a view materialization in dbt
- Include appropriate dbt model configuration (materialization type)
- Add documentation blocks for a schema.yml
- Add descriptions for tables and columns
- Include relevant tests
- Define primary keys and relationships
- Assume that upstream objects are models
- Comprehensively provide all the columns in the output
- Break complex procedures into multiple models if needed
- Implement appropriate incremental strategies for large tables
- Use Snowflake SQL functions rather than macros whenever possible
- Always cast columns with explicit precision/scale using
::TYPE syntax (e.g.,
column_name::VARCHAR(100), amount::NUMBER(18,2)) to ensure output matches expected data types
- Always provide explicit column aliases for clarity and documentation
Performance Optimization
- Suggest clustering keys if needed
- Recommend materialization strategy (view vs table)
- Identify potential performance improvements
BigQuery to Snowflake Syntax Conversion
- Convert backtick identifiers (`project.dataset.table`) to Snowflake format
- Replace UNNEST with LATERAL FLATTEN
- Convert STRUCT/ARRAY types to VARIANT/ARRAY
- Translate SAFE** functions to TRY** equivalents
- Convert IS TRUE/IS FALSE operators
- Handle DATE/TIMESTAMP differences
- Replace ARRAY_AGG with Snowflake equivalent
- Convert BigQuery-specific window functions
Key Data Type Mappings
| BigQuery |
Snowflake |
Notes |
| INT64/INT/INTEGER/BIGINT |
INT |
Alias for NUMBER(38,0) |
| SMALLINT/TINYINT/BYTEINT |
Same |
|
| NUMERIC/DECIMAL/BIGNUMERIC |
NUMERIC |
BIGNUMERIC may lose precision |
| FLOAT64 |
FLOAT |
|
| BOOL/BOOLEAN |
BOOLEAN |
|
| STRING |
VARCHAR |
|
| BYTES |
BINARY |
|
| DATE |
DATE |
|
| TIME |
TIME |
|
| DATETIME |
TIMESTAMP_NTZ |
|
| TIMESTAMP |
TIMESTAMP_TZ |
BigQuery stores in UTC |
| ARRAY |
ARRAY |
|
| STRUCT |
VARIANT |
Use OBJECT_CONSTRUCT |
| JSON |
VARIANT |
Use PARSE_JSON |
| GEOGRAPHY |
GEOGRAPHY |
|
| INTERVAL |
VARCHAR |
|
Key Syntax Conversions
-- Backtick identifiers → Double quotes
`project.dataset.table` → "project"."dataset"."table"
-- UNNEST → LATERAL FLATTEN
SELECT * FROM table, UNNEST(array_col) AS elem →
SELECT * FROM table, LATERAL FLATTEN(input => array_col) AS f
-- STRUCT → OBJECT_CONSTRUCT
STRUCT(1 AS a, 'x' AS b) → OBJECT_CONSTRUCT('a', 1, 'b', 'x')
-- ARRAY access
array_col[OFFSET(0)] → array_col[0]
array_col[ORDINAL(1)] → array_col[0]
-- SAFE_* functions → TRY_* or :: with TRY_
SAFE_CAST(x AS INT64) → TRY_TO_NUMBER(x)::INTEGER
SAFE_CAST(x AS STRING) → x::VARCHAR -- regular cast when safe
SAFE_DIVIDE(a, b) → a / NULLIF(b, 0) -- returns NULL on divide by zero
-- IS TRUE/IS FALSE
WHERE col IS TRUE → WHERE col = TRUE
-- ARRAY_AGG
ARRAY_AGG(col) → ARRAY_AGG(col)
-- JSON functions
JSON_VALUE(col, '$.key') → col:key::STRING
Common Function Mappings
| BigQuery |
Snowflake |
Notes |
IF(cond, a, b) |
IFF(cond, a, b) |
|
IFNULL(a, b) |
IFNULL(a, b) |
Same |
COUNTIF(cond) |
COUNT_IF(cond) |
|
LOGICAL_AND(col) |
BOOLAND_AGG(col) |
|
LOGICAL_OR(col) |
BOOLOR_AGG(col) |
|
SAFE_CAST(x AS type) |
TRY_CAST(x AS type) |
|
ARRAY_CONCAT(a, b) |
ARRAY_CAT(a, b) |
|
ARRAY_LENGTH(arr) |
ARRAY_SIZE(arr) |
|
FORMAT_DATE(fmt, d) |
TO_CHAR(d, fmt) |
Format codes differ |
CURRENT_DATETIME() |
CURRENT_TIMESTAMP()::TIMESTAMP_NTZ |
|
JSON_VALUE(col, '$.key') |
col:key::STRING |
Path syntax differs |
JSON_EXTRACT_SCALAR(...) |
JSON_EXTRACT_PATH_TEXT(...) |
|
STARTS_WITH(str, prefix) |
STARTSWITH(str, prefix) |
|
ENDS_WITH(str, suffix) |
ENDSWITH(str, suffix) |
|
REGEXP_CONTAINS(val, re) |
REGEXP_INSTR(val, re) > 0 |
|
TIMESTAMP_MILLIS(ms) |
TO_TIMESTAMP(ms / 1000) |
|
UNIX_MILLIS(ts) |
DATE_PART('epoch_millisecond', ts) |
|
ST_GEOGFROMTEXT(wkt) |
ST_GEOGRAPHYFROMWKT(wkt) |
|
ST_GEOGPOINT(lon, lat) |
ST_POINT(lon, lat) |
|
Dependencies
- List any upstream dependencies
- Suggest model organization in dbt project
Validation Checklist
- [] Every DDL statement has been accounted for in the dbt models
- [] SQL in models is compatible with Snowflake
- [] BigQuery-specific syntax converted (UNNEST, backticks, STRUCT/ARRAY)
- [] All business logic preserved
- [] All columns included in output
- [] Data types correctly mapped
- [] Functions translated to Snowflake equivalents
- [] Materialization strategy selected
- [] Tests added
- [] SQL logic description complete
- [] Table descriptions added
- [] Column descriptions added
- [] Dependencies correctly mapped
- [] Incremental logic (if applicable) verified
- [] Inline comments added for converted syntax
Related Skills
- $dbt-migration - For the complete migration workflow (discovery, planning, placeholder models,
testing, deployment)
- $dbt-modeling - For CTE patterns and SQL structure guidance
- $dbt-testing - For implementing comprehensive dbt tests
- $dbt-architecture - For project organization and folder structure
- $dbt-materializations - For choosing materialization strategies (view, table, incremental,
snapshots)
- $dbt-performance - For clustering keys, warehouse sizing, and query optimization
- $dbt-commands - For running dbt commands and model selection syntax
- $dbt-core - For dbt installation, configuration, and package management
- $snowflake-cli - For executing SQL and managing Snowflake objects
Supported Source Database
| Database |
Key Considerations |
| Google BigQuery |
UNNEST, STRUCT/ARRAY types, backtick identifiers, IS TRUE/FALSE operators, SAFE_* functions |
Translation References
Detailed syntax translation guides are available in the translation-references/ folder.
Copyright Notice: The translation reference documentation in this repository is derived from
Snowflake SnowConvert Documentation
and is © Copyright Snowflake Inc. All rights reserved. Used for reference purposes only.
Reference Index
- Create Table
- Create View
- Data Types
- Functions
- Identifiers
- Operators
- Overview (README)
- Subqueries
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: dbt-migration-bigquery3description: Transform Google BigQuery DDL (views, tables, stored procedures) into production-quality dbt models Use when this capability is needed.4---56# BigQuery to dbt Model Conversion78## Purpose910Transform Google BigQuery DDL (views, tables, stored procedures) into production-quality dbt models11compatible with Snowflake, maintaining the same business logic and data transformation steps while12following dbt best practices.1314## When to Use This Skill1516Activate this skill when users ask about:1718- Converting BigQuery views or tables to dbt models19- Migrating BigQuery stored procedures to dbt20- Translating BigQuery SQL syntax to Snowflake21- Generating schema.yml files with tests and documentation22- Handling BigQuery-specific syntax conversions (UNNEST, STRUCT/ARRAY, backtick identifiers)2324---2526## Task Description2728You are a database engineer working for a hospital system. You need to convert BigQuery DDL to29equivalent dbt code compatible with Snowflake, maintaining the same business logic and data30transformation steps while following dbt best practices.3132## Input Requirements3334I will provide you the BigQuery DDL to convert.3536## Audience3738The code will be executed by data engineers who are learning Snowflake and dbt.3940## Output Requirements4142Generate the following:43441. One or more dbt models with complete SQL for every column452. A corresponding schema.yml file with appropriate tests and documentation463. A config block with materialization strategy474. Explanation of key changes and architectural decisions485. Inline comments highlighting any syntax that was converted4950## Conversion Guidelines5152### General Principles5354- Replace procedural logic with declarative SQL where possible55- Break down complex procedures into multiple modular dbt models56- Implement appropriate incremental processing strategies57- Maintain data quality checks through dbt tests58- Use Snowflake SQL functions rather than macros whenever possible5960### Sample Response Format6162```sql63-- dbt model: models/[domain]/[target_schema_name]/model_name.sql64{{ config(materialized='view') }}6566/* Original Object: [project].[dataset].[object_name]67 Source Platform: BigQuery68 Purpose: [brief description]69 Conversion Notes: [key changes]70 Description: [SQL logic description] */7172WITH source_data AS (73 SELECT74 -- INT64 converted to INTEGER75 customer_id::INTEGER AS customer_id,76 -- STRING converted to VARCHAR77 customer_name::VARCHAR(100) AS customer_name,78 -- NUMERIC converted to NUMBER79 account_balance::NUMBER(18,2) AS account_balance,80 -- TIMESTAMP converted to TIMESTAMP_TZ (BigQuery stores UTC)81 created_date::TIMESTAMP_TZ AS created_date82 FROM {{ ref('upstream_model') }}83),8485transformed_data AS (86 SELECT87 customer_id,88 UPPER(customer_name)::VARCHAR(100) AS customer_name_upper,89 account_balance,90 created_date,91 CURRENT_TIMESTAMP()::TIMESTAMP_NTZ AS loaded_at92 FROM source_data93)9495SELECT96 customer_id,97 customer_name_upper,98 account_balance,99 created_date,100 loaded_at101FROM transformed_data102```103104```yaml105## models/[domain]/[target_schema_name]/_models.yml106version: 2107108models:109 - name: model_name110 description: "Table description; converted from BigQuery [Original object name]"111 columns:112 - name: customer_id113 description: "Primary key - unique customer identifier"114 tests:115 - unique116 - not_null117 - name: customer_name_upper118 description: "Customer name in uppercase"119 - name: account_balance120 description: "Current account balance; Foreign key to OTHER_TABLE"121 tests:122 - relationships:123 to: ref('OTHER_TABLE')124 field: OTHER_TABLE_KEY125 - name: created_date126 description: "Date the customer record was created"127 - name: loaded_at128 description: "Timestamp when the record was loaded by dbt"129```130131```yaml132## dbt_project.yml (excerpt)133models:134 my_project:135 +materialized: view136 domain_name:137 +schema: target_schema_name138```139140### Specific Translation Rules141142#### dbt Specific Requirements143144- If the source is a view, use a view materialization in dbt145- Include appropriate dbt model configuration (materialization type)146- Add documentation blocks for a schema.yml147- Add descriptions for tables and columns148- Include relevant tests149- Define primary keys and relationships150- Assume that upstream objects are models151- Comprehensively provide all the columns in the output152- Break complex procedures into multiple models if needed153- Implement appropriate incremental strategies for large tables154- Use Snowflake SQL functions rather than macros whenever possible155- **Always cast columns with explicit precision/scale** using `::TYPE` syntax (e.g.,156 `column_name::VARCHAR(100)`, `amount::NUMBER(18,2)`) to ensure output matches expected data types157- **Always provide explicit column aliases** for clarity and documentation158159#### Performance Optimization160161- Suggest clustering keys if needed162- Recommend materialization strategy (view vs table)163- Identify potential performance improvements164165#### BigQuery to Snowflake Syntax Conversion166167- Convert backtick identifiers (\`project.dataset.table\`) to Snowflake format168- Replace UNNEST with LATERAL FLATTEN169- Convert STRUCT/ARRAY types to VARIANT/ARRAY170- Translate SAFE*\* functions to TRY*\* equivalents171- Convert IS TRUE/IS FALSE operators172- Handle DATE/TIMESTAMP differences173- Replace ARRAY_AGG with Snowflake equivalent174- Convert BigQuery-specific window functions175176#### Key Data Type Mappings177178| BigQuery | Snowflake | Notes |179| -------------------------- | ------------- | ----------------------------- |180| INT64/INT/INTEGER/BIGINT | INT | Alias for NUMBER(38,0) |181| SMALLINT/TINYINT/BYTEINT | Same | |182| NUMERIC/DECIMAL/BIGNUMERIC | NUMERIC | BIGNUMERIC may lose precision |183| FLOAT64 | FLOAT | |184| BOOL/BOOLEAN | BOOLEAN | |185| STRING | VARCHAR | |186| BYTES | BINARY | |187| DATE | DATE | |188| TIME | TIME | |189| DATETIME | TIMESTAMP_NTZ | |190| TIMESTAMP | TIMESTAMP_TZ | BigQuery stores in UTC |191| ARRAY<T> | ARRAY | |192| STRUCT | VARIANT | Use OBJECT_CONSTRUCT |193| JSON | VARIANT | Use PARSE_JSON |194| GEOGRAPHY | GEOGRAPHY | |195| INTERVAL | VARCHAR | |196197#### Key Syntax Conversions198199```sql200-- Backtick identifiers → Double quotes201`project.dataset.table` → "project"."dataset"."table"202203-- UNNEST → LATERAL FLATTEN204SELECT * FROM table, UNNEST(array_col) AS elem →205SELECT * FROM table, LATERAL FLATTEN(input => array_col) AS f206207-- STRUCT → OBJECT_CONSTRUCT208STRUCT(1 AS a, 'x' AS b) → OBJECT_CONSTRUCT('a', 1, 'b', 'x')209210-- ARRAY access211array_col[OFFSET(0)] → array_col[0]212array_col[ORDINAL(1)] → array_col[0]213214-- SAFE_* functions → TRY_* or :: with TRY_215SAFE_CAST(x AS INT64) → TRY_TO_NUMBER(x)::INTEGER216SAFE_CAST(x AS STRING) → x::VARCHAR -- regular cast when safe217SAFE_DIVIDE(a, b) → a / NULLIF(b, 0) -- returns NULL on divide by zero218219-- IS TRUE/IS FALSE220WHERE col IS TRUE → WHERE col = TRUE221222-- ARRAY_AGG223ARRAY_AGG(col) → ARRAY_AGG(col)224225-- JSON functions226JSON_VALUE(col, '$.key') → col:key::STRING227```228229#### Common Function Mappings230231| BigQuery | Snowflake | Notes |232| -------------------------- | ------------------------------------ | ------------------- |233| `IF(cond, a, b)` | `IFF(cond, a, b)` | |234| `IFNULL(a, b)` | `IFNULL(a, b)` | Same |235| `COUNTIF(cond)` | `COUNT_IF(cond)` | |236| `LOGICAL_AND(col)` | `BOOLAND_AGG(col)` | |237| `LOGICAL_OR(col)` | `BOOLOR_AGG(col)` | |238| `SAFE_CAST(x AS type)` | `TRY_CAST(x AS type)` | |239| `ARRAY_CONCAT(a, b)` | `ARRAY_CAT(a, b)` | |240| `ARRAY_LENGTH(arr)` | `ARRAY_SIZE(arr)` | |241| `FORMAT_DATE(fmt, d)` | `TO_CHAR(d, fmt)` | Format codes differ |242| `CURRENT_DATETIME()` | `CURRENT_TIMESTAMP()::TIMESTAMP_NTZ` | |243| `JSON_VALUE(col, '$.key')` | `col:key::STRING` | Path syntax differs |244| `JSON_EXTRACT_SCALAR(...)` | `JSON_EXTRACT_PATH_TEXT(...)` | |245| `STARTS_WITH(str, prefix)` | `STARTSWITH(str, prefix)` | |246| `ENDS_WITH(str, suffix)` | `ENDSWITH(str, suffix)` | |247| `REGEXP_CONTAINS(val, re)` | `REGEXP_INSTR(val, re) > 0` | |248| `TIMESTAMP_MILLIS(ms)` | `TO_TIMESTAMP(ms / 1000)` | |249| `UNIX_MILLIS(ts)` | `DATE_PART('epoch_millisecond', ts)` | |250| `ST_GEOGFROMTEXT(wkt)` | `ST_GEOGRAPHYFROMWKT(wkt)` | |251| `ST_GEOGPOINT(lon, lat)` | `ST_POINT(lon, lat)` | |252253#### Dependencies254255- List any upstream dependencies256- Suggest model organization in dbt project257258---259260## Validation Checklist261262- [] Every DDL statement has been accounted for in the dbt models263- [] SQL in models is compatible with Snowflake264- [] BigQuery-specific syntax converted (UNNEST, backticks, STRUCT/ARRAY)265- [] All business logic preserved266- [] All columns included in output267- [] Data types correctly mapped268- [] Functions translated to Snowflake equivalents269- [] Materialization strategy selected270- [] Tests added271- [] SQL logic description complete272- [] Table descriptions added273- [] Column descriptions added274- [] Dependencies correctly mapped275- [] Incremental logic (if applicable) verified276- [] Inline comments added for converted syntax277278---279280## Related Skills281282- $dbt-migration - For the complete migration workflow (discovery, planning, placeholder models,283 testing, deployment)284- $dbt-modeling - For CTE patterns and SQL structure guidance285- $dbt-testing - For implementing comprehensive dbt tests286- $dbt-architecture - For project organization and folder structure287- $dbt-materializations - For choosing materialization strategies (view, table, incremental,288 snapshots)289- $dbt-performance - For clustering keys, warehouse sizing, and query optimization290- $dbt-commands - For running dbt commands and model selection syntax291- $dbt-core - For dbt installation, configuration, and package management292- $snowflake-cli - For executing SQL and managing Snowflake objects293294---295296## Supported Source Database297298| Database | Key Considerations |299| ------------------- | --------------------------------------------------------------------------------------------- |300| **Google BigQuery** | UNNEST, STRUCT/ARRAY types, backtick identifiers, IS TRUE/FALSE operators, SAFE\_\* functions |301302## Translation References303304Detailed syntax translation guides are available in the `translation-references/` folder.305306> **Copyright Notice:** The translation reference documentation in this repository is derived from307> [Snowflake SnowConvert Documentation](https://docs.snowflake.com/en/migrations/snowconvert-docs)308> and is © Copyright Snowflake Inc. All rights reserved. Used for reference purposes only.309310### Reference Index311312- [Create Table](translation-references/bigquery-create-table.md)313- [Create View](translation-references/bigquery-create-view.md)314- [Data Types](translation-references/bigquery-data-types.md)315- [Functions](translation-references/bigquery-functions.md)316- [Identifiers](translation-references/bigquery-identifiers.md)317- [Operators](translation-references/bigquery-operators.md)318- [Overview (README)](translation-references/bigquery-readme.md)319- [Subqueries](translation-references/bigquery-subqueries.md)320321---322> Converted and distributed by [TomeVault](https://tomevault.io/claim/sfc-gh-dflippo) — claim your Tome and manage your conversions.323<!-- tomevault:4.0:skill_md:2026-04-11 -->