DWH Interview Question 4 - What is the difference between ETL and ELT?

Data Warehouse Interview Q&A · Question 4

In this post we are going to cover the difference between ETL and ELT. Both are ways of moving data from source systems into a data warehouse, and the only difference in the name is the order of two letters. That order matters a lot.

ETL stands for Extract, Transform, Load: data is cleaned in a separate engine before it is loaded into the warehouse. ELT stands for Extract, Load, Transform: raw data is loaded into the warehouse first, and transformed there, usually with SQL.

We will walk through how each one works, then run a real ELT transform in SQL: load a messy CSV export as is, and clean it inside the warehouse.

Question 4 of the Real DWH Question and Answers series on TechBrothersIT.

The interview answer

Say this first

ETL (Extract, Transform, Load) transforms data in a separate engine before it is loaded into the warehouse. ELT (Extract, Load, Transform) loads raw data first, then transforms it inside the warehouse, usually with SQL. Modern cloud warehouses favor ELT because their compute scales on demand.

How ETL works: transform, then load

ETL is the classic approach. It has three steps, in this order:

  • Extract - the pipeline reads data from the source systems, like the shop database and a CSV export from the payment provider.
  • Transform - a separate ETL engine cleans the data, fixes data types, removes duplicates, joins sources together and calculates totals. Tools like SSIS, Informatica or DataStage did this for years.
  • Load - only the clean, finished tables are written into the warehouse.

The benefit is that the warehouse only ever sees clean data, and sensitive fields can be masked before they arrive. The cost is that the raw data is not in the warehouse, and every new question means changing the pipeline.

How ELT works: load, then transform

ELT is the modern approach. Extract is the same, but then we load the data straight into the warehouse, exactly as it arrived. This first layer is often called raw, or staging.

Then we transform inside the warehouse, with SQL. The warehouse engine does the heavy lifting, and the clean result goes into new tables. Tools like dbt organize these SQL transformations.

Because the raw data is kept, we can fix a bug and simply re-run the transform, or build a new table for a new question, without touching the sources again. This fits cloud warehouses like Snowflake, BigQuery, Redshift and Databricks, where storage is cheap and compute scales up when you need it.

Let's create some sample data

This setup is the Load step of ELT. We create a raw_orders table where every column is text, and load a CSV export into it as is. We also create an empty, properly typed orders_clean table for the analysts.

Sample data — run this first
DROP TABLE IF EXISTS raw_orders;
DROP TABLE IF EXISTS orders_clean;

-- ELT step 1 (Load): the CSV export is loaded AS IS. Everything is text.
CREATE TABLE raw_orders (
  order_id   VARCHAR(20),
  customer   VARCHAR(50),
  city       VARCHAR(50),
  amount     VARCHAR(20),
  order_date VARCHAR(20)
);
INSERT INTO raw_orders VALUES
  ('1001', 'Sara Khan ', ' toronto',  '35.00', '2026-01-05'),
  ('1002', 'Omar Ali',   'Dallas ',   '25.00', '2026-01-09'),
  ('1002', 'Omar Ali',   'Dallas ',   '25.00', '2026-01-09'),
  ('1003', 'Lina Park',  'seattle',   '30',    '2026-02-02'),
  ('1004', 'Mei Chen',   'VANCOUVER', '27.00', '2026-03-03');

-- the clean, typed table the analysts will use
CREATE TABLE orders_clean (
  order_id   INT,
  customer   VARCHAR(50),
  city       VARCHAR(50),
  amount     DECIMAL(10,2),
  order_date DATE
);

Let's look at the raw data closely.

Query
SELECT * FROM raw_orders ORDER BY 1;
Result5 rows · 5 columns
order_idcustomercityamountorder_date
1001Sara Khan toronto35.002026-01-05
1002Omar AliDallas 25.002026-01-09
1002Omar AliDallas 25.002026-01-09
1003Lina Parkseattle302026-02-02
1004Mei ChenVANCOUVER27.002026-03-03

There is a lot wrong here. Sara Khan has a trailing space and toronto a leading one, the cities are in mixed case, Lina's amount is 30 with no decimals, every column is stored as text, and order 1002 appears twice.

Step 1: Transform the raw data with SQL

Now the Transform step, inside the warehouse, in plain SQL. DISTINCT removes the duplicate, TRIM removes the spaces, UPPER standardizes the city, and CAST turns text into proper numbers and dates.

Statement
INSERT INTO orders_clean
SELECT DISTINCT
       CAST(order_id AS INT),
       TRIM(customer),
       UPPER(TRIM(city)),
       CAST(amount AS DECIMAL(10,2)),
       CAST(order_date AS DATE)
FROM raw_orders;

Now let's check the result.

Query
SELECT * FROM orders_clean ORDER BY order_id;
Result4 rows · 5 columns
order_idcustomercityamountorder_date
1001Sara KhanTORONTO35.002026-01-05
1002Omar AliDALLAS25.002026-01-09
1003Lina ParkSEATTLE30.002026-02-02
1004Mei ChenVANCOUVER27.002026-03-03

We get a clean, typed table: four orders, one per row. Order 1002 appears only once, every city is upper case with no spaces, and Lina's amount is now 30.00. The raw table is still in the warehouse, so if we change a rule tomorrow, we just run the transform again.

Step 2: Analysts query the clean table

Because the data is clean and typed, the report is a simple GROUP BY.

Query
SELECT city, SUM(amount) AS sales
FROM orders_clean
GROUP BY city
ORDER BY sales DESC;
Result4 rows · 2 columns
citysales
TORONTO35.00
SEATTLE30.00
VANCOUVER27.00
DALLAS25.00

Each city appears once: TORONTO 35.00, SEATTLE 30.00, VANCOUVER 27.00 and DALLAS 25.00. Dallas is 25.00, not 50.00, because the duplicate order 1002 was removed in the transform. The analyst did not need to know about any of the problems in the raw file.

ETL vs ELT side by side

Here is the comparison to walk through in the interview.

ETLELT
TRANSFORMSeparate engine, before loadingInside the warehouse, after loading
RAW DATAUsually not kept in the warehouseKept: easy to re-process
COMPUTEETL servers or serviceWarehouse compute (scales)
TOOLSSSIS, Informatica, DataStage, ADFSnowflake, BigQuery, Databricks + dbt
SENSITIVE DATAMask before loadingMask and control access in the warehouse

Choosing between them

  • ELT - a cloud warehouse or lakehouse, lots of data, and analysts who know SQL. Today, that is most new projects.
  • ETL - sensitive data must be removed before it lands, the target system has limited compute, or you already run a mature ETL platform.
  • Both - real pipelines often do light cleanup on the way in and heavy modeling in the warehouse. Some people call that ETLT.
Common mistake

Don't say "ETL is dead." It is not. The real question is where the transform runs best.

Follow-up questions interviewers ask

Is ETL dead?

No. It still fits when sensitive data must be removed before landing, when target compute is limited, or with mature ETL platforms.

What is ETLT?

A mix: light cleanup during extract/load, heavy modeling inside the warehouse.

Where does dbt fit?

dbt organizes, tests and documents the SQL transformations of an ELT pipeline inside the warehouse.

The full script

Here is everything from this post in one script. Copy it and run it top to bottom.

Full script — copy and run top to bottom
-- ========================================================================
-- Data Warehouse Interview Q&A #4 - ETL vs ELT
-- TechBrothersIT. Sample data is invented for teaching.
-- Standard SQL, tested on PostgreSQL 16. Runs top to bottom in one go.
-- Run it in an empty database or schema: other videos reuse table names
-- like dim_customer, and their leftover tables can block the DROPs below.
-- PostgreSQL example:  CREATE SCHEMA dwh_q04;  SET search_path TO dwh_q04;
-- ========================================================================

-- Step 0: create and load the sample data
DROP TABLE IF EXISTS raw_orders;
DROP TABLE IF EXISTS orders_clean;

-- ELT step 1 (Load): the CSV export is loaded AS IS. Everything is text.
CREATE TABLE raw_orders (
  order_id   VARCHAR(20),
  customer   VARCHAR(50),
  city       VARCHAR(50),
  amount     VARCHAR(20),
  order_date VARCHAR(20)
);
INSERT INTO raw_orders VALUES
  ('1001', 'Sara Khan ', ' toronto',  '35.00', '2026-01-05'),
  ('1002', 'Omar Ali',   'Dallas ',   '25.00', '2026-01-09'),
  ('1002', 'Omar Ali',   'Dallas ',   '25.00', '2026-01-09'),
  ('1003', 'Lina Park',  'seattle',   '30',    '2026-02-02'),
  ('1004', 'Mei Chen',   'VANCOUVER', '27.00', '2026-03-03');

-- the clean, typed table the analysts will use
CREATE TABLE orders_clean (
  order_id   INT,
  customer   VARCHAR(50),
  city       VARCHAR(50),
  amount     DECIMAL(10,2),
  order_date DATE
);


-- Step 1: ELT step 2 (Transform): clean the raw data with SQL inside the warehouse
INSERT INTO orders_clean
SELECT DISTINCT
       CAST(order_id AS INT),
       TRIM(customer),
       UPPER(TRIM(city)),
       CAST(amount AS DECIMAL(10,2)),
       CAST(order_date AS DATE)
FROM raw_orders;

-- check the result
SELECT * FROM orders_clean ORDER BY order_id;

-- Step 2: Analysts query the clean table
SELECT city, SUM(amount) AS sales
FROM orders_clean
GROUP BY city
ORDER BY sales DESC;

Key points

  • ETL: transform in a separate engine, then load clean data
  • ELT: load raw data first, transform inside the warehouse with SQL
  • ELT keeps raw data, so transforms can be re-run any time
  • ETL can mask sensitive data before it lands
  • Cloud projects mostly use ELT; many pipelines mix both
Next in this series

Question 5 — What is a data lake? What is a data lake, and why put it in front of the warehouse?

Every query and every result on this page was run on PostgreSQL 16 using the script above. The SQL is standard and runs on most databases with small changes (noted in the script). All tables and data are invented demo data for teaching.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.