Product & Business Growth Analysis Using SQL
A boardroom-ready growth story told through SQL — covering volume trends, efficiency gains, channel diversification, product revenue, and cross-sell performance across Maven Fuzzy Factory’s full business history.
The Brief
Maven Fuzzy Factory is preparing to present to investors. The CEO needs a comprehensive, data-backed story of how the business has grown — from its very first sessions in 2012 to where it stands in early 2015. The task: translate the raw database into a compelling growth narrative using SQL.
This project covers 8 business questions across volume growth, efficiency metrics, channel performance, product revenue, and cross-sell analysis. Every number below was pulled directly from the database — no estimates, no assumptions.
Q1 — Overall Volume Growth by Quarter
Can you pull overall session and order volume, trended by quarter for the life of the business? Since the most recent quarter is incomplete, you can decide how to handle it.
To answer this, I joined website_sessions with orders on website_session_id and grouped by year and quarter. The most recent quarter (2015 Q1) was incomplete at the time of analysis — I included it with a note since it still shows strong trajectory.
SELECT YEAR(ws.created_at) AS year, QUARTER(ws.created_at) AS quarter, COUNT(DISTINCT ws.website_session_id) AS sessions, COUNT(DISTINCT o.order_id) AS orders FROM website_sessions ws LEFT JOIN orders o USING (website_session_id) GROUP BY 1, 2;
Results (Selected Quarters)
| Year | Quarter | Sessions | Orders |
|---|---|---|---|
| 2012 | Q1 | 1,879 | 60 |
| 2012 | Q2 | 11,433 | 347 |
| 2012 | Q4 | 32,266 | 1,495 |
| 2013 | Q2 | 24,745 | 1,718 |
| 2013 | Q4 | 40,540 | 2,616 |
| 2014 | Q2 | 53,129 | 3,848 |
| 2014 | Q4 | 76,373 | 5,908 |
| 2015 | Q1* | 64,198 | 5,420 |
* 2015 Q1 is an incomplete quarter
Sessions grew from 1,879 in 2012 Q1 to a peak of 76,373 in 2014 Q4 — a 40× increase in under 3 years. Order volume followed the same curve, growing from 60 to 5,908 over the same period. Q4 consistently outperforms other quarters, pointing to strong seasonality.
Q2 — Quarterly Efficiency Metrics
I would love to show quarterly figures since we launched, for session-to-order conversion rate, revenue per order, and revenue per session.
This query extends Q1 by adding revenue aggregation and three calculated efficiency metrics. All three are computed inline as derived columns.
SELECT YEAR(ws.created_at) AS year, QUARTER(ws.created_at) AS quarter, COUNT(DISTINCT ws.website_session_id) AS sessions, COUNT(DISTINCT o.order_id) AS orders, SUM(o.price_usd) AS revenue, COUNT(DISTINCT o.order_id) / COUNT(DISTINCT ws.website_session_id) AS session_to_order_cvr, SUM(o.price_usd) / COUNT(DISTINCT o.order_id) AS rev_per_order, SUM(o.price_usd) / COUNT(DISTINCT ws.website_session_id) AS rev_per_session FROM website_sessions ws LEFT JOIN orders o USING (website_session_id) GROUP BY 1, 2;
Results (Selected Quarters)
| Year | Q | CVR | Rev/Order | Rev/Session |
|---|---|---|---|---|
| 2012 | Q1 | 3.19% | $49.99 | $1.60 |
| 2012 | Q4 | 4.63% | $49.99 | $2.32 |
| 2013 | Q1 | 6.42% | $52.14 | $3.35 |
| 2013 | Q4 | 6.45% | $54.72 | $3.53 |
| 2014 | Q1 | 6.56% | $62.16 | $4.08 |
| 2014 | Q4 | 7.74% | $63.79 | $4.93 |
| 2015 | Q1 | 8.44% | $62.80 | $5.30 |
All three efficiency metrics improved dramatically. CVR more than doubled from 3.19% to 8.44%. Revenue per order grew from $49.99 to $62.80 as new higher-priced products were introduced. Revenue per session — the single best metric of business efficiency — grew 3.3× from $1.60 to $5.30. The business got significantly better at converting and monetizing its traffic over time.
Q3 — Orders by Channel, Quarterly
Could you pull a quarterly view of orders from Gsearch nonbrand, Bsearch nonbrand, brand search overall, organic search, and direct type-in?
Each channel is isolated using a CASE WHEN expression inside COUNT(DISTINCT), filtering on utm_source, utm_campaign, and http_referer to correctly categorize sessions.
SELECT YEAR(ws.created_at) AS year, QUARTER(ws.created_at) AS quarter, COUNT(DISTINCT CASE WHEN utm_source = 'gsearch' AND utm_campaign = 'nonbrand' THEN o.order_id END) AS gsearch_nonbrand, COUNT(DISTINCT CASE WHEN utm_source = 'bsearch' AND utm_campaign = 'nonbrand' THEN o.order_id END) AS bsearch_nonbrand, COUNT(DISTINCT CASE WHEN utm_campaign = 'brand' THEN o.order_id END) AS brand_orders, COUNT(DISTINCT CASE WHEN utm_source IS NULL AND http_referer IS NULL THEN o.order_id END) AS direct_type_in, COUNT(DISTINCT CASE WHEN utm_source IS NULL AND http_referer IS NOT NULL THEN o.order_id END) AS organic_search FROM website_sessions ws LEFT JOIN orders o USING (website_session_id) GROUP BY 1, 2;
Results (Selected Quarters)
| Year | Q | Gsearch NB | Bsearch NB | Brand | Direct | Organic |
|---|---|---|---|---|---|---|
| 2012 | Q1 | 60 | 0 | 0 | 0 | 0 |
| 2012 | Q4 | 913 | 311 | 88 | 89 | 94 |
| 2013 | Q2 | 1,114 | 237 | 114 | 119 | 134 |
| 2013 | Q4 | 1,657 | 291 | 248 | 197 | 223 |
| 2014 | Q2 | 2,208 | 427 | 410 | 367 | 436 |
| 2015 | Q1 | 3,025 | 581 | 622 | 552 | 640 |
The business started almost entirely dependent on Gsearch nonbrand. By 2015 Q1, brand search, organic, and direct each contributed over 550 orders per quarter — nearly matching Bsearch nonbrand. This channel diversification significantly reduces paid search dependency and is a strong signal of brand equity building over time.
Q4 — Conversion Rate Trends by Channel
Please show the overall session-to-order conversion rate trends for those same channels, by quarter. Please also make a note of any periods where we made major improvements or optimizations.
Note: This query calculates sessions ÷ orders — a higher number means more sessions are needed per order, so lower is better. The 2012 Q1 and Q2 figures are extremely high due to sparse early data.
SELECT YEAR(ws.created_at) AS year, QUARTER(ws.created_at) AS quarter, COUNT(DISTINCT CASE WHEN utm_source = 'gsearch' AND utm_campaign = 'nonbrand' THEN ws.website_session_id END) / COUNT(DISTINCT CASE WHEN utm_source = 'gsearch' AND utm_campaign = 'nonbrand' THEN o.order_id END) AS gsearch_sessions_per_order, -- (repeat pattern for bsearch, brand, direct, organic) COUNT(DISTINCT CASE WHEN utm_source IS NULL AND http_referer IS NOT NULL THEN ws.website_session_id END) / COUNT(DISTINCT CASE WHEN utm_source IS NULL AND http_referer IS NOT NULL THEN o.order_id END) AS organic_sessions_per_order FROM website_sessions ws LEFT JOIN orders o USING (website_session_id) GROUP BY 1, 2;
Results (Selected Quarters)
| Year | Q | Gsearch NB | Bsearch NB | Brand | Direct | Organic |
|---|---|---|---|---|---|---|
| 2012 | Q3 | 26.06 | 24.50 | 16.63 | 22.56 | 20.08 |
| 2013 | Q1 | 16.33 | 14.44 | 14.22 | 16.29 | 13.29 |
| 2013 | Q4 | 15.90 | 16.65 | 12.49 | 15.46 | 14.41 |
| 2014 | Q2 | 14.24 | 14.39 | 12.44 | 13.55 | 12.54 |
| 2015 | Q1 | 11.62 | 11.77 | 11.74 | 12.91 | 12.18 |
Sessions required per order dropped significantly across every channel — from ~26 in mid-2012 to ~12 by 2015 Q1, meaning the site roughly doubled its conversion efficiency. The biggest improvement happened between 2012 and early 2013, likely driven by A/B testing and landing page optimizations made during that period. By 2015, all channels are converging around 11–13 sessions per order.
Q5 — Monthly Revenue & Margin by Product
We’ve come a long way since selling a single product. Let’s pull monthly trending for revenue and margin by product, along with total sales and revenue. Note anything you notice about seasonality.
This query pulls from order_items and uses CASE WHEN to pivot each product’s revenue and margin into its own column. I track all four products: Mr. Fuzzy (P1), The Forever Love Bear (P2), The Birthday Sugar Panda (P3), and Hudson River Mini Bear (P4).
SELECT YEAR(created_at) AS year, MONTH(created_at) AS month, SUM(CASE WHEN product_id = 1 THEN price_usd END) AS mr_fuzzy_rev, SUM(CASE WHEN product_id = 1 THEN price_usd - cogs_usd END) AS mr_fuzzy_margin, SUM(CASE WHEN product_id = 2 THEN price_usd END) AS love_bear_rev, SUM(CASE WHEN product_id = 2 THEN price_usd - cogs_usd END) AS love_bear_margin, -- repeat for products 3 and 4 SUM(price_usd) AS total_rev, SUM(cogs_usd) AS total_cogs FROM order_items GROUP BY 1, 2 ORDER BY 1, 2;
Results (Selected Months)
| Period | Mr. Fuzzy | Love Bear | Sugar Panda | Mini Bear | Total Rev |
|---|---|---|---|---|---|
| 2012-03 | $2,999 | — | — | — | $2,999 |
| 2012-11 | $30,894 | — | — | — | $30,894 |
| 2013-01 | $17,147 | $2,820 | — | — | $19,966 |
| 2013-12 | $40,892 | $10,978 | $6,393 | — | $58,263 |
| 2014-02 | $29,194 | $21,056 | $9,704 | $6,058 | $66,013 |
| 2014-11 | $72,535 | $22,616 | $19,546 | $13,466 | $128,163 |
| 2014-12 | $79,184 | $23,216 | $24,789 | $17,634 | $144,823 |
| 2015-01 | $69,586 | $23,636 | $20,696 | $18,294 | $132,212 |
The business launched with a single product (Mr. Fuzzy) and grew to four by early 2014. November and December consistently show the highest revenue across all years — clear holiday seasonality. December 2014 hit a peak of $144,823 in total revenue. Mr. Fuzzy remains the top revenue driver, but the newer products now collectively contribute nearly 50% of monthly revenue, reducing single-product risk significantly.
Q6 — Products Page: Click-Through & Conversion Trends
Pull monthly sessions to the /products page, and show how the % of those sessions clicking through another page has changed over time, along with a view of how conversion from /products to placing an order has improved.
This required a CTE to first isolate sessions that visited the /products page, then left joining back to website_pageviews (on session ID with a pageview ID greater than the products pageview) to find those that clicked further, and to orders to capture conversions.
WITH ms_product_pg AS ( SELECT website_session_id, website_pageview_id, created_at AS product_pg_seen_at FROM website_pageviews WHERE pageview_url = '/products' ) SELECT YEAR(product_pg_seen_at) AS year, MONTH(product_pg_seen_at) AS month, COUNT(DISTINCT ms.website_session_id) AS sessions_to_products, COUNT(DISTINCT wp.website_session_id) AS clicked_next_pg, COUNT(DISTINCT wp.website_session_id) / COUNT(DISTINCT ms.website_session_id) AS clickthrough_rate, COUNT(DISTINCT o.order_id) AS orders, COUNT(DISTINCT o.order_id) / COUNT(DISTINCT ms.website_session_id) AS products_to_order_rt FROM ms_product_pg ms LEFT JOIN website_pageviews wp ON ms.website_session_id = wp.website_session_id AND ms.website_pageview_id < wp.website_pageview_id LEFT JOIN orders o ON o.website_session_id = ms.website_session_id GROUP BY 1, 2;
Results (Selected Months)
| Period | Sessions | Clicked Next | CTR | Orders | → Order Rate |
|---|---|---|---|---|---|
| 2012-03 | 743 | 530 | 71.3% | 60 | 8.1% |
| 2012-12 | 5,013 | 3,620 | 72.2% | 506 | 10.1% |
| 2013-06 | 4,600 | 3,536 | 76.9% | 594 | 12.9% |
| 2014-01 | 7,790 | 6,387 | 82.0% | 983 | 12.6% |
| 2014-09 | 11,128 | 9,156 | 82.3% | 1,424 | 12.8% |
| 2014-12 | 17,240 | 14,609 | 84.7% | 2,314 | 13.4% |
| 2015-03 | 9,022 | 7,723 | 85.6% | 1,254 | 13.9% |
The /products page click-through rate climbed from 71% to 85.6% — users are increasingly engaging past the product listing. Products-to-order conversion improved from 8.1% to 13.9%, nearly a 72% lift. The introduction of new products gave visitors more reasons to explore and buy. The combination of better UX and a richer product catalog is clearly working.
Q7 — Cross-Sell Analysis After Product 4 Launch
We made our 4th product available as a primary product on December 05, 2014. Could you please pull sales data since then, and show how well each product cross-sells from one another?
This uses a temporary table to capture all orders placed after December 5, 2014, then joins back to order_items filtering on is_primary_item = 0 to identify cross-sell items. Each product’s cross-sell rate is computed as a ratio of total orders.
CREATE TEMPORARY TABLE primary_products SELECT order_id, primary_product_id, created_at AS ordered_at FROM orders WHERE created_at > '2014-12-05'; SELECT primary_product_id, COUNT(DISTINCT order_id) AS total_orders, COUNT(DISTINCT CASE WHEN cross_sell_product_id = 1 THEN order_id END) AS xsold_p1, COUNT(DISTINCT CASE WHEN cross_sell_product_id = 4 THEN order_id END) AS xsold_p4, COUNT(DISTINCT CASE WHEN cross_sell_product_id = 4 THEN order_id END) / COUNT(DISTINCT order_id) AS xsold_p4_rt FROM ( SELECT pp.*, oi.product_id AS cross_sell_product_id FROM primary_products pp LEFT JOIN order_items oi ON oi.order_id = pp.order_id AND oi.is_primary_item = 0 ) AS pp_w_xsell GROUP BY 1;
Results
| Primary Product | Total Orders | X-sell P1 | X-sell P2 | X-sell P3 | X-sell P4 | P4 Rate |
|---|---|---|---|---|---|---|
| P1 — Mr. Fuzzy | 4,467 | — | 238 (5.3%) | 553 (12.4%) | 933 (20.9%) | 20.9% |
| P2 — Love Bear | 1,277 | 25 (2.0%) | — | 40 (3.1%) | 260 (20.4%) | 20.4% |
| P3 — Sugar Panda | 929 | 84 (9.0%) | 40 (4.3%) | — | 208 (22.4%) | 22.4% |
| P4 — Mini Bear | 581 | 16 (2.8%) | 9 (1.5%) | 22 (3.8%) | — | — |
Product 4 (Hudson River Mini Bear) is an exceptional cross-sell item — it’s being added to ~20% of all orders regardless of the primary product. P1 (Mr. Fuzzy) generates the most cross-sell volume in absolute terms given its dominance as primary product. P4 cross-selling to P3 leads at 22.4%. This data strongly supports keeping P4 as a prominent cross-sell option and potentially testing it as a bundle add-on at checkout.
Q8 — Recommendations & Opportunities
Based on all the analysis you’ve done, could you share some recommendations and opportunities for us going forward?
The data tells a strong growth story — but it also reveals clear opportunities the business can act on next:
November and December consistently produce 2–3× the revenue of slower months. The business should plan inventory, paid spend, and promotions well ahead of Q4 to maximise this window. A dedicated holiday campaign strategy with product bundles could push December revenue even higher.
With a ~20% cross-sell rate across all primary products, the Mini Bear is clearly a natural add-on. Testing a “Add for $X more at checkout” prompt could increase attach rate from 20% to 30%+ without additional traffic spend.
Brand search, organic, and direct now each contribute 550+ orders per quarter — nearly matching Bsearch nonbrand paid spend. These are essentially free or low-cost conversions. Investing in SEO content and brand awareness now will compound returns over the next 12–24 months.
Click-through rate from /products climbed to 85.6% but there’s still ~14% of visitors who don’t click through. Testing richer product imagery, clearer CTAs, or a featured product section could push this rate above 90% and drive meaningful incremental orders.
View the Full Project on GitHub
Complete SQL file with all 8 queries, comments, and temp table logic.
