dbt Development Conventions
Based on the dbt style guide. Most SQL rules are enforced by sqlfluff.
Naming
- Schema, table and column names in
PascalCase, e.g.DimBucket,FactUser,StgLegacyCountryState - CTEs in
snake_case, e.g.dim_bucket - Marts are named after business terminology and stay source agnostic
- Prefix facts with
Fact, dimensions withDim, stage models withStg - Stage models are based on source terminology and are the first step of any modelling
- Stage column names stay close to raw data unless logic is applied
Data types
- Timestamps in UTC. Other time zones get a suffix, e.g.
CreatedAtPT - Date columns carry a precision suffix, e.g.
CreatedAt,EventTime - Booleans prefixed
IsorHas, typedTRUE/FALSErather than0/1orYes/No
Keys
- Primary keys of facts and dimensions use the
surrogate_keymacro fromdbt_utils- Dimensions: built from the source primary key - Facts: built from the keys of the associated dimensions - Dimension primary key:
<ObjectName>Key - Fact primary key:
Fact<ObjectName>Key
SQL style
- Trailing commas
- Four-space indents, eight inside parentheses (
sqlfluff4.x) - Lines up to 200 characters
- Field names, tables, Jinja keywords, functions and syntactic keywords in lowercase
- Always use
aswhen aliasing - Spaces inside Jinja delimiters:
{{ this }} select * from ()is writtenselect *, newline,from ()- Do not optimise for fewer lines: newlines are cheap, brain time is expensive
Best practices
- Aggregate as early as possible, before joining
- Prefer
union alltounion - Be explicit about joins (
inner join, notjoin);left joinis usually the most useful,right joinsuggests swapping thefromtable - Use
on, neverusing(inconsistent results inSnowflake) - With two or more tables, prefix every column with the table alias; recommended for one table too
- Avoid initialisms for aliases:
user, notu - State grouping fields before aggregates and window functions