Start learning free

LESSON 47 OF 107 · DATA ENGINEERING: DBT

A Model Is a SELECT in a File

Practice

In chapter 2 you built stg_orders by hand with CREATE TABLE … AS SELECT. Data teams do this work with dbt (data build tool). In dbt, a model is one SELECT saved in a .sql file in the models/ folder. The command dbt build wraps each SELECT in the CREATE for you and names the result after the file. Unless you ask for something else, a model becomes a view: a saved query that runs its SELECT each time it is read. Teams use dbt because every table's SQL lives in plain files they can review, keep in git and rebuild with one command.

For example, this file, models/stg_customers.sql, makes a view named stg_customers from a customers table, with customer_id turned into a number. There is no CREATE and no semicolon: dbt adds what it needs around your SELECT.

models/stg_customers.sql

SELECT
    CAST(customer_id AS INTEGER) AS customer_id,
    city
FROM raw_customers

At work you type dbt build in a terminal, and the warehouse is Snowflake or BigQuery. Here the grader runs dbt build for you, and the warehouse is the DuckDB file shop.duckdb. A loader has already put the 78 orders in it as the table raw_orders, every column as text. On order 5030 the quantity is the word two.

You edit one file, models/stg_orders.sql. It starts with four columns and no FROM, so dbt build prints model stg_orders (view): ERROR with DuckDB's message: Referenced column "order_id" was not found because the FROM clause is missing. When your model is done, the check runs dbt build, lists the tables in the warehouse and the types of stg_orders' columns, and shows its first 3 rows:

model stg_orders (view): OK
table_name | table_type
raw_orders | BASE TABLE
stg_orders | VIEW
(2 rows)
column_name | data_type
order_id | VARCHAR
customer_id | VARCHAR
product | VARCHAR
quantity | INTEGER
unit_price | INTEGER
status | VARCHAR
ordered_at | TIMESTAMP
(7 rows)
stg_orders (view), 78 rows, the first 3:
order_id | customer_id | product | quantity | unit_price | status | ordered_at
5001 | 49 | Gift card | 1 | 50 | paid | 2026-05-01 08:25:00
5002 | 96 | Pen | 1 | 2 | paid | 2026-05-01 10:45:00
5003 | 254 | Notebook | 1 | 7 | paid | 2026-05-01 11:01:00

Your task: in models/stg_orders.sql, make the SELECT read the table raw_orders, and give three columns their types: quantity as an INTEGER with TRY_CAST, unit_price as an INTEGER and ordered_at as a TIMESTAMP, each keeping its name.


Assignment
Follow the Coding Tutorial to turn models/stg_orders.sql into your first dbt model: a FROM line and three typed columns.


Hint
Write only the SELECT: no CREATE, no semicolon. TRY_CAST turns the word two into NULL where CAST would stop with an error. Name each cast column with AS, and leave the comma off the last column before FROM.


STEP 1 OF 4
    Ctrl + Enter to check