← Back to list

Day 18: dbt Macros — Automating Repetitive SQL Tasks in dbt

🚀 Welcome back to our dbt series!

G Hari Krishna in The Data Movement · 2025-02-20 04:36 · 9 claps · 3.0 min read paywalled
#dbt #dbt-labs #dbt-macro #sql-macros #data-engineering
Open on Medium ↗
Wiki topics: 🔧 · Data Engineering

Day 18: dbt Macros — Automating Repetitive SQL Tasks in dbt

🚀 Welcome back to our dbt series!

Today, we’re diving into dbt macros, one of the most powerful features that help automate repetitive SQL tasks and make your code cleaner, more efficient, and reusable.

If you’ve worked on enterprise data transformations, you know how painful it can be to:

🔹 Write the same logic in multiple models 🔹 Maintain complex SQL queries across hundreds of files 🔹 Apply transformations dynamically based on environment (dev, prod, staging, etc.)

Solution? 👉 dbt Macros

Let’s explore what macros are, why they matter, and how to use them in real-world scenarios.

1️⃣ What Are dbt Macros?

A macro in dbt is a reusable piece of SQL logic that you can call in multiple models. It’s like a function in Python but for SQL!

Macros are written using Jinja, dbt’s templating language, and can:

Eliminate duplicate codeMake SQL logic dynamicImprove maintainability & readabilityAdapt queries based on environments

Example Use Cases:

🔹 Generate surrogate keys dynamically 🔹 Handle incremental loads efficiently 🔹 Apply standardized column naming 🔹 Run dynamic partitioning logic

2️⃣ Creating a Simple dbt Macro

📂 Project Structure

dbt_project/
│── models/
│   ├── staging/
│   │   ├── stg_orders.sql
│── macros/
│   ├── generate_surrogate_key.sql
│── dbt_project.yml

Step 1: Define a Macro

📂 Create macros/generate_surrogate_key.sql

{% macro generate_surrogate_key(columns) %}
    md5(concat({{ columns | join(', ') }}))
{% endmacro %}

Here’s what’s happening:

  • columns is a list of column names
  • concat({{ columns | join(', ') }}) joins them into a single string
  • md5() generates a unique hash (surrogate key)

Step 2: Use the Macro in a Model

📂 models/staging/stg_orders.sql

WITH source AS (
    SELECT
        order_id,
        customer_id,
        order_date,
        total_amount,
        {{ generate_surrogate_key(['order_id', 'customer_id']) }} AS order_key
    FROM {{ source('raw', 'orders') }}
)
SELECT * FROM source;

🚀 Boom! Now every order gets a unique surrogate key, without writing the same MD5 logic in every model!

3️⃣ Parameterized Macros — Making SQL Dynamic

Let’s create a macro that dynamically selects the latest records from any table.

📂 macros/get_latest_records.sql

{% macro get_latest_records(table_name, timestamp_col) %}
    SELECT * 
    FROM {{ table_name }} 
    WHERE {{ timestamp_col }} = (SELECT MAX({{ timestamp_col }}) FROM {{ table_name }})
{% endmacro %}

Use it in a model:

📂 models/staging/stg_latest_orders.sql

{{ get_latest_records('staging.orders', 'order_date') }}

🎯 This saves time and makes SQL much cleaner!

4️⃣ Advanced Example: Dynamic Incremental Logic

Let’s take incremental processing to the next level with macros.

Step 1: Create an Incremental Macro

📂 macros/incremental_filter.sql

{% macro incremental_filter(column_name) %}
    {% if is_incremental() %}
        WHERE {{ column_name }} > (SELECT MAX({{ column_name }}) FROM {{ this }})
    {% endif %}
{% endmacro %}

Step 2: Use It in a Model

📂 models/incremental_orders.sql

SELECT * 
FROM {{ source('raw', 'orders') }}
{{ incremental_filter('order_date') }}

🔹 If the model runs for the first time, it loads all data. 🔹 If it’s an incremental run, it only picks new records!

5️⃣ Running Macros in dbt

Macros can be executed directly from the CLI:

dbt run-operation generate_surrogate_key --args '{columns: ["order_id", "customer_id"]}'

This is useful for debugging and testing macros before using them in models!

6️⃣ Best Practices for Writing dbt Macros

Use meaningful macro names (e.g., generate_surrogate_key, not macro_1) ✅ Keep them modular – A macro should do one thing wellUse parameters wisely – Make macros reusable across projects ✅ Document them – Add comments and docstrings for team collaboration ✅ Test them in CLI before using them in models

7️⃣ Business Impact of Using Macros in Enterprise dbt Projects

📌 Less Code Duplication — One macro, multiple use cases 📌 📌 Standardized SQL Practices — Everyone follows the same rules 📌 📌 Scalability — Easily adapt logic across hundreds of models 📌 📌 Faster Development — Engineers write less SQL, focus on data insights

🔹 Example in Real-World Enterprise Data Teams

At a Fortune 500 e-commerce company:

  • Macros helped automate currency conversion calculations across 50+ models
  • A single data validation macro reduced SQL errors by 40%
  • A dynamic incremental load macro cut dbt processing time by 30%

8️⃣ Key Takeaways

dbt Macros automate repetitive SQL logicThey improve code efficiency, maintainability, and scalabilityEnterprise data teams can standardize SQL best practicesDynamic macros make SQL adaptive across environments

🚀 Next Up: Using Jinja for Advanced SQL Templating in dbt!

💬 Do you use dbt macros in your workflow? Share your experience! 👇


메타데이터
post_id
9bb85b97ae6f
slug
day-18-dbt-macros-automating-repetitive-sql-tasks-in-dbt-9bb85b97ae6f
url
https://medium.com/the-data-movement/day-18-dbt-macros-automating-repetitive-sql-tasks-in-dbt-9bb85b97ae6f
canonical_url
https://medium.com/the-data-movement/day-18-dbt-macros-automating-repetitive-sql-tasks-in-dbt-9bb85b97ae6f
author_url
https://medium.com/@gharikrishnade
status
ok
fetched_at
2026-08-08 18:38:31