Module 2 of 16

Tables, Grain, and Why Dashboards Lie

Learn the most important beginner concept: one row per what?

Updated

90 minutes1 exercisesFree

Start here

Learning objectives

  • Define table grain accurately
  • Spot double-counting bugs before they reach dashboards
  • Understand facts, dimensions, and event tables
Tables, Grain, and Why Dashboards Lie Follow the arrows. Each box is one idea you will practice in this module. Table step 1 Grain step 2 Join step 3 Aggregate step 4 Check step 5 Production analytics engineering turns raw records into governed, trusted business meaning.

The Mental Model

Grain means what one row represents. Most bad metrics come from joining tables with different grains and then aggregating without noticing the duplication.

Before writing any SQL, ask: one row per what? If you cannot answer, you are not ready to aggregate.

Dataset reference: ecommerce tables and grain assumptions.

Measure join fanout before aggregating

Order 101 is worth 100 and has two line items. Order 102 is worth 50 and has one. This standalone SQL example compares an unsafe join with a calculation at order grain.

with orders(order_id, amount) as (values (101, 100), (102, 50)),
items(order_id, item_id) as (values (101, 1), (101, 2), (102, 3))
select
  (select sum(o.amount) from orders o
   join items i on i.order_id = o.order_id) as unsafe_total,
  (select sum(amount) from orders) as order_total;

Expected result: unsafe_total = 250; order_total = 150. The extra 100 is the repeated order amount. SUM(DISTINCT amount) is not a repair: two different orders can have the same amount. Aggregate items to one row per order before joining, or aggregate the order fact separately.

Acceptance check: compare row count and distinct order count before and after every join intended to preserve order grain.

Interactive Check

Question: You join orders to order_items and then sum order amount. Why might revenue become too high?

Reveal the answer

Each order can have many items. The order amount repeats once per item after the join, so summing it counts the same order multiple times.

Practice: Find the Grain

Identify the grain of five sample tables and decide whether each can be safely joined before aggregation.

Use the guided lab below to record your result, assumptions, and the check that would catch an incorrect result.

Production notes

Keep these close

  • Add model descriptions that start with grain: "One row per..." This prevents many review mistakes.

Common mistakes

What usually breaks

  • Summing order-level values after item-level joins
  • Assuming unique IDs without testing them
  • Mixing event time and reporting time without naming the difference

Key terms

Vocabulary used in this module

Grain

The real-world entity or event represented by one row.

Fact table

A table containing measurable business events such as orders or payments.

Exercises

Practice inside the lesson

30-45 minutesBeginner

Find the Grain

Identify the grain of five sample tables and decide whether each can be safely joined before aggregation.

  1. Label raw_orders as one row per order
  2. Label raw_order_items as one row per order item
  3. Label raw_customers as one row per customer
  4. Explain why orders to order_items is one-to-many
  5. Write the safe aggregation rule

Expected evidence

A short answer, SQL/YAML snippet, or lineage map that can live directly in the course page notes.

Recap

Key takeaways

  • Always state grain before aggregating
  • One-to-many joins are the main source of dashboard lies
  • Facts and dimensions are useful because they make grain explicit

Related resources

Keep learning across CodersSecret