What if you could write one query that magically creates many for you?
Why For loops for dynamic SQL in dbt? - Purpose & Use Cases
Imagine you have to write SQL queries for each month of the year manually. You copy and paste the same query 12 times, changing only the month value each time.
This manual method is slow and boring. It's easy to make mistakes like typos or forgetting to update a month. If you want to add more months or change the query, you must edit every copy again.
Using for loops for dynamic SQL lets you write one loop that automatically creates all the monthly queries. This saves time, reduces errors, and makes your code easy to update.
SELECT * FROM sales WHERE month = 'January'; SELECT * FROM sales WHERE month = 'February'; -- repeated for each month
{% set months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] %}
{% for month in months %}
SELECT * FROM sales WHERE month = '{{ month }}';
{% endfor %}You can generate many SQL queries dynamically with just a few lines of code, making your work faster and more reliable.
A data analyst uses a for loop in dbt to create monthly sales reports automatically, instead of writing separate queries for each month.
Manual SQL repetition is slow and error-prone.
For loops automate query generation dynamically.
This approach saves time and reduces mistakes.
Practice
{% for %} loops in dbt SQL models?Solution
Step 1: Understand the role of
The{% for %}in dbt{% for %}loop is used to repeat code blocks dynamically in dbt SQL models.Step 2: Identify the benefit of repeating code
Repeating code patterns saves time and reduces errors by avoiding manual copy-pasting.Final Answer:
To repeat SQL code patterns dynamically and reduce manual repetition -> Option DQuick Check:
For loops = dynamic repetition [OK]
- Thinking for loops create tables
- Confusing dbt loops with Python loops
- Believing loops stop queries
Solution
Step 1: Recall dbt Jinja syntax for loops
dbt uses Jinja templating where loops start with{% for variable in sequence %}.Step 2: Compare options to correct syntax
Only {% for item in list %} matches the correct Jinja for loop syntax.Final Answer:
{% for item in list %} -> Option CQuick Check:
dbt for loop syntax = {% for %} [OK]
- Using {{ }} instead of {% %} for loops
- Using wrong keywords like 'loop'
- Using angle brackets instead of curly braces
{% for col in ['id', 'name', 'age'] %}SELECT {{ col }} FROM users{% if not loop.last %} UNION ALL {% endif %}{% endfor %}Solution
Step 1: Understand the loop iteration
The loop runs over ['id', 'name', 'age'], producing three SELECT statements.Step 2: Check the UNION ALL insertion
Between each SELECT except the last, 'UNION ALL' is added to combine results.Final Answer:
SELECT id FROM users UNION ALL SELECT name FROM users UNION ALL SELECT age FROM users -> Option AQuick Check:
Loop + UNION ALL = combined selects [OK]
- Ignoring the UNION ALL between selects
- Assuming all columns selected in one query
- Thinking commas separate selects
{% for col in columns %}SELECT {{ col }} FROM users{% endfor %}Assuming
columns = ['id', 'name'].Solution
Step 1: Analyze the loop output
The loop outputs two SELECT statements back to back without any separator.Step 2: Identify missing SQL syntax
Without UNION ALL or a separator, the SQL is invalid and will cause errors.Final Answer:
Missing UNION ALL or separator between SELECT statements -> Option BQuick Check:
Multiple SELECTs need UNION ALL [OK]
- Forgetting to add UNION ALL
- Using wrong loop syntax
- Misnaming variables inside loop
Solution
Step 1: Filter columns inside the for loop
{% for col in columns if col %}SELECT {{ col }} FROM users{% if not loop.last %} UNION ALL {% endif %}{% endfor %} usesfor col in columns if colto skip empty or None values correctly.Step 2: Add UNION ALL only between valid selects
{% for col in columns if col %}SELECT {{ col }} FROM users{% if not loop.last %} UNION ALL {% endif %}{% endfor %} adds UNION ALL only if not the last valid column, avoiding trailing UNION ALL.Final Answer:
{% for col in columns if col %}SELECT {{ col }} FROM users{% if not loop.last %} UNION ALL {% endif %}{% endfor %} -> Option AQuick Check:
Filter in loop + conditional UNION ALL = correct [OK]
- Using incorrect if condition syntax
- Adding UNION ALL after last select
- Not filtering out empty or None columns
Ready to prove it?
Pass the test and this pattern moves unknown
