2.7 KiB
2.7 KiB
name, description
| name | description |
|---|---|
| dbt_sql_style | General SQL style guide for writing dbt models: CTE structure, formatting conventions, keywords, joins, CASE WHEN, and aggregations. Reusable across any dbt project. |
SQL Style Guide for dbt Models
Apply these conventions to all SQL written in dbt models. Consistent style improves readability and code review speed.
Core Rules
| Rule | Convention |
|---|---|
| Keywords | lowercase (select, from, where, join, group by, order by) |
| Indentation | 4 spaces — no tabs |
| Commas | Trailing (end of line), not leading |
| One column per line | Always — no inline column lists |
| Final SELECT | select * from <last_cte_name> |
CTE Structure
Always use CTEs instead of subqueries. Name each CTE after the source or concept it represents.
with source as (
select * from {{ source('system', 'table') }}
),
renamed as (
select
---------- ids
id_column,
---------- strings
name_column as readable_name,
---------- dates
date_column as event_date,
---------- numerics
amount_column as total_usd
from source
)
select * from renamed
- Blank line after the opening
(and before the closing)of each CTE. - Blank line between each CTE block.
Joins
from orders
left join customers
on orders.customer_id = customers.id
left join products
on orders.product_id = products.id
- Always use
left joinunless you have a specific reason for inner/cross. - Never use bare
join— always be explicit. - Always qualify columns with table/CTE alias when joining multiple sources.
- Place
onconditions on the next line, indented 4 spaces.
CASE WHEN
case
when status = 'cancelled' and cancelled_date is not null
then cancelled_date
when status = 'expired'
then expiration_date
else created_date
end as effective_date,
- One
whencondition per line. thenindented 4 spaces underwhen.- Always include
else. - Close with
end as <alias>.
Aggregations
select
region,
order_type,
count(*) as order_count,
sum(net_value) as total_net_value_usd
from orders
group by 1, 2
- Use positional references in
group by(e.g.,group by 1, 2). - Name aggregated columns clearly:
sum(x) as total_x.
Column Naming Conventions
| Type | Pattern | Example |
|---|---|---|
| Boolean | is_* / has_* |
is_cancelled, has_attachment |
| Date | *_date |
created_date, shipped_date |
| Timestamp | *_at |
created_at, updated_at |
| Numeric amount | *_<unit> |
total_usd, quantity_ea |
| Foreign key | <entity>_id |
customer_id, order_id |