E-commerce analytics blends the two patterns you’ve already built: peer comparison (Chapter 01) and time-based comparison (Chapter 02) - then adds a third dimension unique to this domain: the customer as the unit of analysis over their entire relationship with the business. Customer Lifetime Value, repeat purchase behavior, and order-level ranking all require looking at a customer’s or product’s full history, not just a single transaction.
A typical e-commerce schema centers on orders and order line items:
customers (customer_id, customer_name, signup_date, ...)orders (order_id, customer_id FK, order_date, order_total, ...)order_items (order_item_id, order_id FK, product_id FK, quantity, unit_price, ...)products (product_id, product_name, category_id FK, ...)categories (category_id, category_name)Analytics and growth teams use this data to understand who is buying, what they’re buying, and how often they return.
Customer Lifetime Value and repeat-purchase analysis both require comparing a customer’s current order to their own history - not to a fixed group like a department, and not strictly to a calendar period like a fiscal month, but to their own prior orders, in sequence. This is a natural extension of LAG()/LEAD() and running-total patterns, partitioned by customer_id instead of salesperson_id or dept_id. Product and category rankings reuse the exact RANK()/DENSE_RANK() leaderboard pattern from Chapters 01 and 02, now applied to product_id and category_id partitions.
| Function | Business Explanation |
|---|---|
RANK() / DENSE_RANK() |
Customer value leaderboard; product ranking within category. |
SUM() OVER (PARTITION BY customer_id ORDER BY order_date ...) |
Running lifetime revenue per customer. |
LAG() |
Time between a customer’s consecutive orders (repeat purchase gap). |
AVG() OVER (PARTITION BY customer_id) |
Customer’s own historical average order value, for anomaly comparison. |
ROW_NUMBER() |
Identifying each customer’s first order (for cohort and CLV-start analysis). |
ROW_NUMBER() = 1 per customer_id (ordered by order_date) to isolate each customer’s first order, a common building block for cohort and CLV-start analysis.PARTITION BY customer_id) from a “company-level” running total (no partition) - the same distinction introduced in Sales Analytics, now reused for a different grain.COUNT() OVER (PARTITION BY customer_id) to determine whether a customer is a repeat purchaser (count > 1) without a separate aggregation query.customer_id scale well when (customer_id, order_date) is indexed - without it, the engine must sort the entire orders table per partition on every query execution.category_id directly rather than joining to categories purely for the category name inside the window - join the name in an outer SELECT after ranking, if the ranking column itself doesn’t require it.COUNT(*) instead of COUNT(DISTINCT order_id) when counting orders per customer in the presence of a joined order_items table, silently inflating the count by line-item quantity.LAG() will correctly return NULL for such rows, but downstream aggregate calculations must explicitly exclude or handle these NULLs.SUM(order_total) OVER (PARTITION BY customer_id ORDER BY order_date), and a discussion of the difference between “running CLV” and “final/total CLV.”ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) = 1.COUNT() OVER (PARTITION BY customer_id) (or a GROUP BY + HAVING COUNT(*) > 1) to identify repeat purchasers, divided by total customers in the cohort.RANK() OVER (PARTITION BY category_id ORDER BY SUM(revenue) DESC) over a pre-aggregated product-revenue CTE.E-commerce analytics is where peer comparison (Chapter 01) and time-based comparison (Chapter 02) combine and extend to a new grain: the customer’s own history. Running lifetime value, first-order detection, and repeat-purchase gap analysis are the foundational building blocks of nearly every growth and retention dashboard in the industry.
NTILE(4)) for a tiered loyalty program.Next: 03_ECOMMERCE.sql — the fully engineered SQL chapter for this domain.
Previous: 02_SALES_ANALYTICS.md · Module: README · Next chapter: 04_BANKING.md