DE Joins and Aggregations

Two SQL techniques power the majority of analytical queries that data engineers and analysts write: joins and aggregations. Joins combine data from multiple tables. Aggregations summarize data across many rows into meaningful totals, averages, and counts. Together, they answer almost every business question a data warehouse needs to handle.

Understanding Joins

Tables in a relational database or data warehouse store related data separately. Customer information lives in the customers table. Order information lives in the orders table. A join connects these tables so a single query can return data from both simultaneously, matching rows that share a common key.

The Puzzle Pieces Analogy

Imagine two puzzle pieces. One piece shows a customer's name and city. The other shows an order amount and date. Neither piece alone tells the full story. A join connects them along their shared edge — the customer ID — to form a complete picture: which customer placed which order, when, and for how much.

Types of Joins

INNER JOIN

Returns only rows that have a matching value in both tables. If a customer has no orders, they do not appear in the result. If an order has no matching customer (data quality issue), it also disappears.

SELECT c.name, c.city, o.order_id, o.amount
FROM customers c
INNER JOIN orders o ON c.customer_id = o.customer_id;

Customers table:          Orders table:
C001 Sara  Delhi          ORD01 C001 2500
C002 Tom   Mumbai         ORD02 C001 1200
C003 Lin   Seoul          ORD03 C002 800
C004 Ola   Lagos          (no orders for C003 or C004)

INNER JOIN result:
Sara  Delhi  ORD01  2500
Sara  Delhi  ORD02  1200
Tom   Mumbai ORD03  800
(Lin and Ola excluded - no orders)

LEFT JOIN (LEFT OUTER JOIN)

Returns all rows from the left table and matching rows from the right table. If a left-table row has no match, the right-table columns return NULL. This is essential when you need to find customers who have NOT placed any orders.

SELECT c.name, c.city, o.order_id, o.amount
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id;

Result:
Sara  Delhi  ORD01   2500
Sara  Delhi  ORD02   1200
Tom   Mumbai ORD03   800
Lin   Seoul  NULL    NULL    <-- included, no orders found
Ola   Lagos  NULL    NULL    <-- included, no orders found

-- Find customers with zero orders:
SELECT c.name FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
WHERE o.order_id IS NULL;

RIGHT JOIN

The mirror of LEFT JOIN. Returns all rows from the right table and matching rows from the left. In practice, engineers rewrite right joins as left joins by swapping the table order — it is easier to read and reason about.

FULL OUTER JOIN

Returns all rows from both tables, matching where possible and filling NULLs where not. Useful for finding records that exist in one table but not the other, in either direction.

-- Find mismatches: orders without customers OR customers without orders
SELECT c.customer_id AS cust_id_from_customers,
       o.customer_id AS cust_id_from_orders
FROM customers c
FULL OUTER JOIN orders o ON c.customer_id = o.customer_id
WHERE c.customer_id IS NULL OR o.customer_id IS NULL;

CROSS JOIN

Returns every combination of rows from both tables. A table with 100 rows cross-joined with a table of 50 rows produces 5,000 rows. Data engineers use cross joins intentionally when generating all possible combinations — for example, every combination of product and date for a sales forecast grid.

Join Performance Tips

Data engineers write joins that run efficiently on large datasets. Joining on indexed columns runs dramatically faster than joining on unindexed columns. Filtering with WHERE before joining reduces the number of rows the engine must match. Joining on integer keys is faster than joining on long string columns.

Aggregations in Depth

Aggregations transform many rows into fewer summary rows. The GROUP BY clause divides the data into groups; aggregate functions compute one value per group.

Common Aggregate Functions

Function    | Purpose                      | Example
------------|------------------------------|----------------------------------
COUNT(*)    | Count all rows               | Total number of orders
COUNT(col)  | Count non-null values        | Orders with a shipping date
SUM(col)    | Total of all values          | Total revenue
AVG(col)    | Mean value                   | Average order size
MAX(col)    | Highest value                | Largest single order
MIN(col)    | Lowest value                 | Earliest order date

Multi-Level Grouping

GROUP BY can group by multiple columns simultaneously, producing one row per unique combination.

-- Revenue by region AND product category
SELECT
    s.region,
    p.category,
    SUM(f.revenue)     AS total_revenue,
    COUNT(f.order_id)  AS order_count,
    AVG(f.revenue)     AS avg_order_value
FROM fact_sales f
JOIN dim_store   s ON f.store_key   = s.store_key
JOIN dim_product p ON f.product_key = p.product_key
GROUP BY s.region, p.category
ORDER BY s.region, total_revenue DESC;

Combining Joins and Aggregations

The most powerful analytical queries join multiple dimension tables to the fact table and then aggregate the results. This pattern forms the backbone of data warehouse reporting.

-- Monthly revenue per customer city and product category
SELECT
    d.year,
    d.month,
    c.city         AS customer_city,
    p.category     AS product_category,
    SUM(f.revenue) AS monthly_revenue,
    COUNT(*)       AS transactions
FROM fact_sales f
JOIN dim_date     d ON f.date_key    = d.date_key
JOIN dim_customer c ON f.cust_key    = c.cust_key
JOIN dim_product  p ON f.product_key = p.product_key
WHERE d.year = 2024
GROUP BY d.year, d.month, c.city, p.category
ORDER BY d.year, d.month, monthly_revenue DESC;

ROLLUP and CUBE for Summary Totals

ROLLUP and CUBE extend GROUP BY to automatically produce subtotals and grand totals without writing multiple queries.

-- Revenue by region with subtotals and grand total
SELECT region, category, SUM(revenue)
FROM sales_summary
GROUP BY ROLLUP(region, category);

This produces:
- Revenue per (region, category)
- Subtotal per region (all categories combined)
- Grand total (all regions, all categories)

Summary

Joins combine rows from multiple tables based on shared keys, with INNER, LEFT, RIGHT, FULL OUTER, and CROSS variations serving different needs. Aggregations summarize groups of rows using functions like SUM, COUNT, AVG, MAX, and MIN. Combining joins with aggregations across dimension and fact tables is the core SQL pattern that powers data warehouse analytics. Writing these efficiently is one of the most practical and frequently used skills in data engineering.

Leave a Comment

Your email address will not be published. Required fields are marked *