Where you would use it
Join one customer row per customer to many transaction rows. A mistaken many-to-many join can multiply revenue and produce plausible-looking but incorrect totals.
GROUP BY and aggregation is a core data-integration operation. In analytics, correctness depends not only on syntax but on the relationship between keys, row cardinality and the grain of each table.
GROUP BY and aggregation is a core data-integration operation. In analytics, correctness depends not only on syntax but on the relationship between keys, row cardinality and the grain of each table.
The practical value of GROUP BY and aggregation comes from understanding both the transformation and the boundary around it: what information is allowed to enter, what assumption is being made, and how you know the result is still valid after the transformation.
A beginner-friendly way to reason about it is to start with a tiny case where the correct result can be checked independently. Once the mechanism is clear, scale the exact same reasoning to larger tables, pipelines or models.
State the grain of each table, identify candidate keys, validate uniqueness where expected, perform the operation, then reconcile row counts and unmatched records.
The interactive view uses a concept-specific plot when the topic maps naturally to one; otherwise it uses a workflow view instead of leaving a broken placeholder.
Join one customer row per customer to many transaction rows. A mistaken many-to-many join can multiply revenue and produce plausible-looking but incorrect totals.
A useful diagnostic question is: Could the same code still run successfully if the analytical assumption were wrong? If yes, add an explicit validation check rather than relying on execution success.
Keep the example small enough that you can inspect each stage manually.
-- Purpose: demonstrate GROUP BY and aggregation with a small, inspectable query.
-- Read each clause in execution context: source rows → conditions → grouping → selected output.
-- Build a named intermediate result so the main query stays readable.
-- Step 1 — Define a named intermediate result (CTE) so the query can be read and checked in stages.
WITH sales(order_id, region, channel, revenue) AS (
VALUES (1,'East','Online',120.0), (2,'West','Store',95.0),
(3,'East','Store',150.0), (4,'West','Online',110.0),
(5,'North','Online',135.0), (6,'East','Online',90.0)
)
-- Choose the columns or calculations to return.
-- Step 2 — Choose the output fields/expressions that the query should return.
SELECT region, COUNT(*) AS orders, ROUND(SUM(revenue),2) AS revenue,
ROUND(AVG(revenue),2) AS avg_order
-- Set the table or intermediate result that supplies rows.
-- Step 3 — Identify the source table or intermediate relation that supplies rows.
FROM sales
-- Group rows so aggregate functions are calculated per group.
-- Step 4 — Create groups that aggregation functions will summarise.
GROUP BY region
-- Sort the final result into a useful reporting order.
-- Step 5 — Sort the final result into a deliberate presentation order.
ORDER BY revenue DESC;region | orders | revenue | avg_order East | 3 | 360.0 | 120.0 North | 1 | 135.0 | 135.0 West | 2 | 205.0 | 102.5