Order and Sales Performance Analysis
This section will explore the order and sales performance metrics for Olist.
5Project Roadmap: Step-by-Step Navigation
Introduction
In this section, we will analyze the following aspects of Olist’s sales performance:
- Monthly Sales Trends. We will examine the monthly sales trends for Olist over the past few years to identify any seasonal patterns or significant flu ctuations in sales performance.
- Pareto Principle for Product Categories. We will identify which product categories constitute the top 20% of sales volume and whether they align with the top 20% of revenue generators. We will also classify categories into ‘High Volume / Low Value’ and ‘Low Volume / High Value’ segments.
- Rolling Average for Revenue. We will calculate the 3-month rolling average for total revenue to smooth out daily and weekly volatility and compare this trendline to the raw sales data to understand the true direction of business growth.
- Regional Sales Distribution. We will analyze how revenue is distributed across different states and cities, identifying the top 5 regions with the highest sales density per capita versus regions with high order volume but low total revenue.
- AOV and Basket Size Analysis. We will analyze the Average Order Value (AOV) and average basket size over time to understand customer purchasing behavior and identify any trends or shifts in these metrics.
Monthly Sales Trends
6. Monthly Sales Trends: What are the monthly sales trends for Olist over the past few years? Are there any seasonal patterns or significant fluctuations in sales performance that can be identified?
Solution:
Solution Steps for Review Response Analysis
-
Firstly, we calculate the time gap for survey responses (
review_response_timesCTE): We use thedatedifffunction to calculate theresponse_time_hoursbetweenreview_creation_date(when the satisfaction survey was sent) andreview_answer_timestamp(when the customer submitted it). We filter out records wherereview_scoreis null. -
Secondly, we segment the response times into analytical cohorts (
response_bucketsCTE): We use aCASEstatement to group the continuous hour values into logical buckets: “Fast (Under 24 Hours)”, “Medium (1 - 3 Days)”, “Slow (3 - 7 Days)”, and “Very Slow (Over 1 Week)”, alongside handling missing timestamps. -
Finally, we aggregate the scores to find correlations (Final
SELECT): We group the results by the newresponse_speed_category. We calculate theavg_review_scorefor each bucket and use conditional summation (sum(case when...)) to find the exact percentage of 1-star and 5-star reviews, revealing how response speed correlates with customer satisfaction.
Show SQL Code
with monthly_sales as (
-- step 1: aggregate core metrics by month
-- we use the calendar table to ensure clean date grouping
select
c.year,
c.month_number,
c.month_name,
count(distinct o.order_id) as total_orders,
sum(p.payment_value) as total_revenue
from
orders o
inner join
payments p on o.order_id = p.order_id
inner join
Calendar c on o.purchase_datekey = c.datekey
where
o.order_status not in ('canceled', 'unavailable')
group by
c.year, c.month_number, c.month_name
),
growth_metrics as (
-- step 2: use lag() to fetch values from the previous month and previous year
select
*,
-- previous month values
prev_month_orders = lag(total_orders) over (order by year, month_number),
prev_month_revenue = lag(total_revenue) over (order by year, month_number),
-- previous year values (offset of 12 rows)
prev_year_orders = lag(total_orders, 12) over (order by year, month_number),
prev_year_revenue = lag(total_revenue, 12) over (order by year, month_number)
from
monthly_sales
)
-- final output: calculating percentage growth
select
year,
month_name,
total_orders,
total_revenue,
-- month-over-month (mom) growth
mom_revenue_growth_pct = cast(100.0 * (total_revenue - prev_month_revenue) / nullif(prev_month_revenue, 0) as decimal(10,2)),
-- year-over-year (yoy) growth
yoy_revenue_growth_pct = cast(100.0 * (total_revenue - prev_year_revenue) / nullif(prev_year_revenue, 0) as decimal(10,2)),
-- identifying seasonal spikes
case
when month_number = 11 then 'Black Friday Period'
when month_number = 12 then 'Holiday Season'
when month_number = 1 then 'New Year Peak'
else 'Standard Period'
end as seasonality_tag
from
growth_metrics
order by
year, month_number;
go
Results:
| year | month_name | total_orders | total_revenue | mom_revenue_growth_pct | yoy_revenue_growth_pct | seasonality_tag |
|---|---|---|---|---|---|---|
| 2016 | September | 1 | 136.22999572753906 | Standard Period | ||
| 2016 | October | 293 | 51657.52999472618 | 37819.35 | Standard Period | |
| 2016 | December | 1 | 19.6200008392334 | -99.96 | Holiday Season | |
| 2017 | January | 787 | 137006.76003867388 | 698201.50 | New Year Peak | |
| 2017 | February | 1718 | 283621.93943831325 | 107.01 | Standard Period | |
| 2017 | March | 2617 | 425656.3995541632 | 50.08 | Standard Period | |
| 2017 | April | 2377 | 405988.3795110285 | -4.62 | Standard Period | |
| 2017 | May | 3640 | 582926.160167003 | 43.58 | Standard Period | |
| 2017 | June | 3205 | 499827.47035080194 | -14.26 | Standard Period | |
| 2017 | July | 3946 | 578858.5795211494 | 15.81 | Standard Period | |
| 2017 | August | 4272 | 662071.7698084246 | 14.38 | Standard Period | |
| 2017 | September | 4227 | 717195.2203616947 | 8.33 | Standard Period | |
| 2017 | October | 4547 | 764785.2796836384 | 6.64 | 561292.72 | Standard Period |
| 2017 | November | 7423 | 1172639.2297811043 | 53.33 | 2170.03 | Black Friday Period |
| 2017 | December | 5620 | 861914.4599985629 | -26.50 | 4392939.87 | Holiday Season |
| 2018 | January | 7187 | 1102639.4091129452 | 27.93 | 704.81 | New Year Peak |
| 2018 | February | 6625 | 979966.2302345932 | -11.13 | 245.52 | Standard Period |
| 2018 | March | 7168 | 1152736.7396906763 | 17.63 | 170.81 | Standard Period |
| 2018 | April | 6919 | 1156303.9107048158 | 0.31 | 184.81 | Standard Period |
| 2018 | May | 6833 | 1145748.6310662013 | -0.91 | 96.55 | Standard Period |
| 2018 | June | 6145 | 1020494.2907593064 | -10.93 | 104.17 | Standard Period |
| 2018 | July | 6233 | 1039880.1590387616 | 1.90 | 79.64 | Standard Period |
| 2018 | August | 6421 | 996896.1512343884 | -4.13 | 50.57 | Standard Period |
| 2018 | September | 1 | 166.4600067138672 | -99.98 | -99.98 | Standard Period |
Insights:
- There is a clear seasonal pattern with significant spikes in revenue during the Black Friday period (November) and the Holiday Season (December). The New Year Peak in January also shows a notable increase in sales.
- The month-over-month growth rates are highly volatile, especially around the holiday season, indicating that raw monthly revenue can be influenced by short-term factors. This underscores the importance of using rolling averages to identify long-term trends.
- The year-over-year growth rates show a strong upward trajectory, particularly in the early months of 2018 compared to 2017, suggesting that Olist is experiencing significant growth year over year, despite the volatility in month-over-month performance.
- The data reveals distinct patterns in product category performance, with some categories driving high sales volumes while others generate substantial revenue per unit sold. This highlights the need for a nuanced approach to inventory and marketing strategies, focusing on both high-volume and high-value categories to optimize overall sales performance.
Pareto Principles for Product Categories
7. Which product categories constitute the top 20% of sales volume, and do they align with the top 20% of revenue generators? Can we identify ‘High Volume / Low Value’ categories versus ‘Low Volume / High Value’ (Niche/Luxury) categories?
Solution:
-
Firstly, we aggregate volume and revenue per category (
category_metricsCTE): We join theorder_items,products, andorderstables to calculate the total number of items sold (total_volume) and the sum of their prices (total_revenue) for eachproduct_category_name. We also ensure to filter out any ‘canceled’ or ‘unavailable’ orders so our metrics reflect actual successful sales. -
Secondly, we calculate the percentile rankings (
category_rankingsCTE): We utilize thepercent_rank()window function, ordering descendingly by volume and revenue respectively. This gives us a statistical ranking from 0 to 1 (volume_percentileandrevenue_percentile), showing exactly where each category stands relative to all others. -
Finally, we segment the categories based on the top 20% thresholds (Final
SELECT): We compute theavg_unit_priceand use aCASEstatement to classify each category. Sincepercent_rank()outputs 0 for the highest value, checking for<= 0.20captures the top 20%. By intersecting the volume and revenue conditions, we can easily identify the ‘High Vol / Low Rev’ (cheap but popular) and ‘Low Vol / High Rev’ (niche/luxury) segments.
Show SQL Code
with category_metrics as (
select
products.product_category_name,
count(order_items.order_item_id) as total_volume,
sum(order_items.price) as total_revenue
from
order_items
inner join
products on products.product_id = order_items.product_id
inner join
orders on orders.order_id = order_items.order_id
where
orders.order_status not in ('canceled', 'unavailable')
and products.product_category_name is not null
group by
products.product_category_name
),
category_rankings as (
select
*,
percent_rank() over (order by total_volume desc) as volume_percentile,
percent_rank() over (order by total_revenue desc) as revenue_percentile
from
category_metrics
)
select
product_category_name,
total_volume,
total_revenue,
cast( total_revenue / total_volume as decimal(10,2)) as avg_unit_price,
case
when volume_percentile <= 0.20 and revenue_percentile <= 0.20 then 'High Vol / High Rev'
when volume_percentile <= 0.20 and revenue_percentile > 0.20 then 'High Vol / Low Rev'
when volume_percentile > 0.20 and revenue_percentile <= 0.20 then 'Low Vol / High Rev'
else 'Standard'
end as category_segmentation
from
category_rankings
order by
total_revenue desc;
Results:
| product_category_name | total_volume | total_revenue | avg_unit_price | category_segmentation |
|---|---|---|---|---|
| beleza_saude | 9634 | 1255695.130966425 | 130.34 | High Vol / High Rev |
| relogios_presentes | 5970 | 1198185.207540512 | 200.70 | High Vol / High Rev |
| cama_mesa_banho | 11097 | 1035964.0600271225 | 93.36 | High Vol / High Rev |
| esporte_lazer | 8590 | 979740.9188661575 | 114.06 | High Vol / High Rev |
| informatica_acessorios | 7781 | 904322.0174894333 | 116.22 | High Vol / High Rev |
| moveis_decoracao | 8298 | 727465.0523052216 | 87.67 | High Vol / High Rev |
| utilidades_domesticas | 6915 | 626825.8007874489 | 90.65 | High Vol / High Rev |
| cool_stuff | 3779 | 620770.4918966293 | 164.27 | High Vol / High Rev |
| automotivo | 4204 | 586585.7307322025 | 139.53 | High Vol / High Rev |
| ferramentas_jardim | 4328 | 481009.94201755524 | 111.14 | High Vol / High Rev |
| brinquedos | 4083 | 479808.5404686928 | 117.51 | High Vol / High Rev |
| bebes | 3043 | 410312.2000389099 | 134.84 | High Vol / High Rev |
| perfumaria | 3402 | 396599.30858802795 | 116.58 | High Vol / High Rev |
| telefonia | 4527 | 322342.6394162178 | 71.20 | High Vol / High Rev |
| moveis_escritorio | 1690 | 273580.70111846924 | 161.88 | Low Vol / High Rev |
| papelaria | 2505 | 229593.83988118172 | 91.65 | Standard |
| pcs | 203 | 222963.1298828125 | 1098.34 | Standard |
| pet_shop | 1942 | 213766.63003492355 | 110.08 | Standard |
| eletroportateis | 671 | 187907.2599811554 | 280.04 | Standard |
| instrumentos_musicais | 669 | 187788.44005393982 | 280.70 | Standard |
| 1589 | 178572.54968833923 | 112.38 | Standard | |
| eletronicos | 2755 | 157079.53940558434 | 57.02 | High Vol / Low Rev |
| consoles_games | 1127 | 154927.27038812637 | 137.47 | Standard |
| fashion_bolsas_e_acessorios | 2025 | 151622.75041007996 | 74.88 | Standard |
| construcao_ferramentas_construcao | 927 | 144550.18987429142 | 155.93 | Standard |
| malas_acessorios | 1088 | 140111.37979125977 | 128.78 | Standard |
| eletrodomesticos_2 | 235 | 110649.73986434937 | 470.85 | Standard |
| casa_construcao | 603 | 83010.11981487274 | 137.66 | Standard |
| eletrodomesticos | 769 | 80001.24019479752 | 104.03 | Standard |
| agro_industria_e_comercio | 212 | 72530.46979904175 | 342.12 | Standard |
| moveis_sala | 501 | 68638.55983161926 | 137.00 | Standard |
| casa_conforto | 434 | 58572.04043722153 | 134.96 | Standard |
| telefonia_fixa | 261 | 57824.20998239517 | 221.55 | Standard |
| climatizacao | 295 | 54723.15971946716 | 185.50 | Standard |
| audio | 363 | 50668.59962081909 | 139.58 | Standard |
| portateis_casa_forno_e_cafe | 76 | 47445.71008014679 | 624.29 | Standard |
| moveis_cozinha_area_de_servico_jantar_e_jardim | 279 | 46070.37002372742 | 165.13 | Standard |
| livros_interesse_geral | 546 | 45622.29049873352 | 83.56 | Standard |
| construcao_ferramentas_iluminacao | 302 | 40002.00014305115 | 132.46 | Standard |
| industria_comercio_e_negocios | 268 | 39669.61002922058 | 148.02 | Standard |
| construcao_ferramentas_seguranca | 189 | 39589.01976776123 | 209.47 | Standard |
| alimentos | 509 | 29243.509969711304 | 57.45 | Standard |
| market_place | 310 | 28288.470039367676 | 91.25 | Standard |
| construcao_ferramentas_jardim | 234 | 25552.180088043213 | 109.20 | Standard |
| artes | 208 | 24167.639976978302 | 116.19 | Standard |
| fashion_calcados | 260 | 23352.87992477417 | 89.82 | Standard |
| bebidas | 378 | 22378.71004676819 | 59.20 | Standard |
| sinalizacao_e_seguranca | 199 | 21509.230089187622 | 108.09 | Standard |
| moveis_quarto | 109 | 20028.77994632721 | 183.75 | Standard |
| livros_tecnicos | 267 | 19096.060108184814 | 71.52 | Standard |
| construcao_ferramentas_ferramentas | 103 | 15903.94997882843 | 154.41 | Standard |
| alimentos_bebidas | 276 | 15119.4800491333 | 54.78 | Standard |
| fashion_roupa_masculina | 131 | 10748.8200340271 | 82.05 | Standard |
| fashion_underwear_e_moda_praia | 131 | 9541.550102233887 | 72.84 | Standard |
| artigos_de_natal | 152 | 8787.830072879791 | 57.81 | Standard |
| tablets_impressao_imagem | 83 | 7528.410045623779 | 90.70 | Standard |
| cine_foto | 72 | 6933.459958076477 | 96.30 | Standard |
| musica | 38 | 6034.349970340729 | 158.80 | Standard |
| livros_importados | 60 | 4639.849992752075 | 77.33 | Standard |
| dvds_blu_ray | 62 | 4559.4899826049805 | 73.54 | Standard |
| artigos_de_festas | 43 | 4485.180006027222 | 104.31 | Standard |
| moveis_colchao_e_estofado | 38 | 4368.079982757568 | 114.95 | Standard |
| portateis_cozinha_e_preparadores_de_alimentos | 14 | 3933.6299953460693 | 280.97 | Standard |
| fashion_roupa_feminina | 48 | 2803.6400108337402 | 58.41 | Standard |
| fashion_esporte | 30 | 2119.510019302368 | 70.65 | Standard |
| la_cuisine | 14 | 2054.9899978637695 | 146.78 | Standard |
| artes_e_artesanato | 24 | 1814.0100049972534 | 75.58 | Standard |
| fraldas_higiene | 38 | 1538.7899932861328 | 40.49 | Standard |
| pc_gamer | 8 | 1306.9500274658203 | 163.37 | Standard |
| flores | 33 | 1110.0400066375732 | 33.64 | Standard |
| casa_conforto_2 | 30 | 760.2699966430664 | 25.34 | Standard |
| cds_dvds_musicais | 14 | 730.0 | 52.14 | Standard |
| fashion_roupa_infanto_juvenil | 8 | 569.8500022888184 | 71.23 | Standard |
| seguros_e_servicos | 2 | 283.2899932861328 | 141.64 | Standard |
Insights: According to the results, we can obtain the following insights:
- Volume and Revenue Align Well: The biggest sellers are also the biggest earners. Categories like beleza_saude (health & beauty), relogios_presentes (watches & gifts), and cama_mesa_banho (bed & bath) are the backbone of the platform, bringing in both massive order counts and top-tier revenue.
- The “High Volume / Low Revenue” Trap: Eletronicos (electronics) fits this perfectly. People buy a lot of them (2,755 units), but because the average item is cheap (just $57.02), the total revenue stays relatively low compared to the effort of shipping that many boxes.
- The “Low Volume / High Revenue” Winners: Moveis_escritorio (office furniture) is our official high-value niche. It only took 1,690 sales to generate over 161.88 average price.
- The Ultimate Premium Outlier: While the system tagged it as “Standard,” pcs (personal computers) is the perfect example of a luxury/high-ticket item. With an average price of 222K—almost matching the revenue of categories that sold thousands of items.
3-Month Rolling Average for Total Revenue
8. Can we calculate the 3-month rolling average for total revenue to smooth out daily and weekly volatility? How does this long-term trendline compare to the raw sales data in identifying the true direction of business growth?
Solution:
-
Firstly, we aggregate the raw monthly revenue (
monthly_revenueCTE): We join theorders,payments, andCalendartables to calculate the totalpayment_value(raw_monthly_revenue) for each month and year. We also filter out ‘canceled’ or ‘unavailable’ orders to ensure we only look at valid sales data. -
Secondly, we calculate the 3-month rolling average (Final
SELECT): We use theavg()window function coupled withrows between 2 preceding and current row. By ordering chronologically by year and month, this smooths out short-term volatility by averaging the current month’s revenue with the two previous months to establish a trendline. -
Finally, we calculate the variance from the trend: We determine how much the current month’s raw revenue deviates from the calculated 3-month rolling average. We compute this as a percentage
((raw - average) / raw) * 100usingnullifto prevent division by zero, which helps easily identify months that significantly overperformed or underperformed the smoothed long-term growth trend.
Show SQL Code
with monthly_revenue as (
select
Calendar.year,
Calendar.month_number,
Calendar.month_name,
sum(payments.payment_value) as raw_monthly_revenue
from
orders
inner join
payments on payments.order_id = orders.order_id
inner join
Calendar on Calendar.datekey = orders.purchase_datekey
where
orders.order_status not in ('canceled', 'unavailable')
group by
Calendar.year, calendar.month_number, Calendar.month_name
)
select
[year],
month_number,
month_name,
raw_monthly_revenue,
-- average the current month and 2 preceding (last) months
cast (avg(raw_monthly_revenue) over (order by [year], month_number
rows between 2 preceding and current row) as decimal(10,3)) as rolling_avg_3m,
-- calculate deviation from the trend = (current_month - rolling_avg_3m) / current_month * 100.0 = var_dev %
cast(100.0 * (raw_monthly_revenue - avg(raw_monthly_revenue) over (order by [year], month_number
rows between 2 preceding and current row)) / nullif(raw_monthly_revenue,0) as decimal (10,2)) as variance_from_trend
from
monthly_revenue
group by
[year],
month_number,
month_name,
raw_monthly_revenue
order by
[year], month_number;
Results:
| year | month_number | month_name | raw_monthly_revenue | rolling_avg_3m | variance_from_trend |
|---|---|---|---|---|---|
| 2016 | 9 | September | 136.22999572753906 | 136.230 | 0.00 |
| 2016 | 10 | October | 51657.52999472618 | 25896.880 | 49.87 |
| 2016 | 12 | December | 19.6200008392334 | 17271.127 | -87928.16 |
| 2017 | 1 | January | 137006.76003867388 | 62894.637 | 54.09 |
| 2017 | 2 | February | 283621.93943831325 | 140216.106 | 50.56 |
| 2017 | 3 | March | 425656.3995541632 | 282095.033 | 33.73 |
| 2017 | 4 | April | 405988.3795110285 | 371755.573 | 8.43 |
| 2017 | 5 | May | 582926.160167003 | 471523.646 | 19.11 |
| 2017 | 6 | June | 499827.47035080194 | 496247.337 | 0.72 |
| 2017 | 7 | July | 578858.5795211494 | 553870.737 | 4.32 |
| 2017 | 8 | August | 662071.7698084246 | 580252.607 | 12.36 |
| 2017 | 9 | September | 717195.2203616947 | 652708.523 | 8.99 |
| 2017 | 10 | October | 764785.2796836384 | 714684.090 | 6.55 |
| 2017 | 11 | November | 1172639.2297811043 | 884873.243 | 24.54 |
| 2017 | 12 | December | 861914.4599985629 | 933112.990 | -8.26 |
| 2018 | 1 | January | 1102639.4091129452 | 1045731.033 | 5.16 |
| 2018 | 2 | February | 979966.2302345932 | 981506.700 | -0.16 |
| 2018 | 3 | March | 1152736.7396906763 | 1078447.460 | 6.44 |
| 2018 | 4 | April | 1156303.9107048158 | 1096335.627 | 5.19 |
| 2018 | 5 | May | 1145748.6310662013 | 1151596.427 | -0.51 |
| 2018 | 6 | June | 1020494.2907593064 | 1107515.611 | -8.53 |
| 2018 | 7 | July | 1039880.1590387616 | 1068707.694 | -2.77 |
| 2018 | 8 | August | 996896.1512343884 | 1019090.200 | -2.23 |
| 2018 | 9 | September | 166.4600067138672 | 678980.923 | -407794.33 |
Insights:
- A Clearer Picture of Growth: The 3-month rolling average successfully smooths out the messy monthly jumps. It reveals a very clean, consistent upward curve throughout 2017 before settling into a steady, flat line in 2018.
- Isolating the Black Friday Boom: In November 2017, raw revenue jumped 24.5% higher than the rolling trendline. This confirms that the Black Friday success was a temporary seasonal spike rather than a permanent shift in baseline sales.
- The Post-Holiday Drop: December 2017 shows an 8.2% negative variance from the trend. Because November pulled the 3-month average so high, this negative variance perfectly illustrates the sudden “hangover” effect as customer spending dropped off.
- Highly Predictable 2018: Between February and August 2018, the raw revenue tracks incredibly closely to the 3-month average. The variance is tiny (mostly between -2% and +6%), showing that the business matured into a very stable phase, predictably earning around 1.15M per month.
- Spotting Bad Data Instantly: The rolling average makes data cutoffs obvious. The massive negative variance in September 2018 immediately flags that our dataset ends abruptly, preventing us from accidentally using that raw number in any serious forecasting.
Revenue Distribution across States and Cities
9. How is revenue distributed across different states (customer_state) and cities? specifically, identifying the top 5 regions with the highest sales density per capita versus regions with high order volume but low total revenue?
Solution:
-
Firstly, we calculate regional baseline metrics (
region_performanceCTE): We join theorders,customers, andpaymentstables to aggregate thetotal_ordersandtotal_revenuefor eachcustomer_stateandcustomer_city. We also calculate theavg_order_value(revenue density) by dividing total revenue by the distinct order count, ensuring we exclude ‘canceled’ or ‘unavailable’ orders. -
Secondly, we rank the regions (
region_rankingsCTE): We use therank()window function to assign arevenue_rankand avolume_rankto each city/state combination. By ordering descendingly, the regions with the highest revenue and order counts receive the top ranks (e.g., Rank 1, 2, 3). -
Finally, we segment the regions based on their rankings (Final
SELECT): We use aCASEstatement to classify each region’s profile by evaluating its volume and revenue ranks. This allows us to categorize regions into distinct business profiles such as ‘Major Economic Hub’ (top ranks in both volume and revenue) or ‘Affluent Niche’ (lower volume rank but high revenue rank), clearly identifying the sales density and distribution across different geographies.
Show SQL Code
with region_performance as (
SELECT
customers.customer_state,
customers.customer_city,
count(distinct orders.order_id) as total_orders,
sum(payments.payment_value) as total_revenue,
-- avg order value -> revenue density
sum(payments.payment_value) / count(distinct orders.order_id) as avg_order_value
FROM
orders
join
customers on customers.customer_id = orders.customer_id
join
payments on payments.order_id = orders.order_id
where
orders.order_status not in ('canceled', 'unavailable')
group by
customers.customer_state,
customers.customer_city
),
region_rankings as (
select
*,
rank() over (order by total_revenue desc) as revenue_rank,
rank() over ( order by total_orders desc) as volume_rank
from
region_performance
)
select
customer_state,
customer_city,
total_orders,
total_revenue,
cast(avg_order_value as decimal(10,2)) as avg_order_value,
case
when revenue_rank <= 10 and volume_rank <= 10 then 'Major Economic Hub (High Vol / High Rev)'
when revenue_rank <= 20 and volume_rank > 50 then 'Affluent Niche (Low Vol / High Rev)'
when revenue_rank <= 10 and volume_rank <= 10 then 'Mass Market (High Vol / Low Rev)'
else 'Standard Market'
end as regional_profile
from
region_rankings
order by
total_revenue desc;
Results:
| customer_state | customer_city | total_orders | total_revenue | avg_order_value | regional_profile |
|---|---|---|---|---|---|
| SP | sao paulo | 15291 | 2150534.770117907 | 140.64 | Major Economic Hub (High Vol / High Rev) |
| RJ | rio de janeiro | 6801 | 1147675.809347108 | 168.75 | Major Economic Hub (High Vol / High Rev) |
| MG | belo horizonte | 2737 | 411571.5802227948 | 150.37 | Major Economic Hub (High Vol / High Rev) |
| DF | brasilia | 2112 | 350563.3297816515 | 165.99 | Major Economic Hub (High Vol / High Rev) |
| PR | curitiba | 1502 | 240889.5599949062 | 160.38 | Major Economic Hub (High Vol / High Rev) |
| RS | porto alegre | 1370 | 220135.7902894616 | 160.68 | Major Economic Hub (High Vol / High Rev) |
| BA | salvador | 1234 | 216352.82025164366 | 175.33 | Major Economic Hub (High Vol / High Rev) |
| SP | campinas | 1422 | 211539.7600118816 | 148.76 | Major Economic Hub (High Vol / High Rev) |
| SP | guarulhos | 1167 | 161739.5199765265 | 138.59 | Major Economic Hub (High Vol / High Rev) |
| RJ | niteroi | 842 | 137399.449943915 | 163.18 | Standard Market |
| SP | sao bernardo do campo | 921 | 118343.4201908093 | 128.49 | Standard Market |
| CE | fortaleza | 647 | 117983.99994421005 | 182.36 | Standard Market |
| GO | goiania | 681 | 117095.89010572433 | 171.95 | Standard Market |
| SP | santos | 706 | 111670.21002027392 | 158.17 | Standard Market |
| PE | recife | 610 | 109421.82003313303 | 179.38 | Standard Market |
| SP | santo andre | 786 | 103892.71011769772 | 132.18 | Standard Market |
| SC | florianopolis | 563 | 99524.4301700592 | 176.78 | Standard Market |
| PA | belem | 440 | 95455.55000805855 | 216.94 | Standard Market |
| SP | osasco | 736 | 93696.3600088805 | 127.30 | Standard Market |
| SP | jundiai | 556 | 91147.71014773846 | 163.93 | Standard Market |
| SP | sao jose dos campos | 683 | 89081.69994664192 | 130.43 | Standard Market |
| SP | sorocaba | 621 | 86911.57992458344 | 139.95 | Standard Market |
| SP | ribeirao preto | 507 | 75379.01995331049 | 148.68 | Standard Market |
| MG | juiz de fora | 425 | 75089.71999931335 | 176.68 | Standard Market |
| RJ | nova iguacu | 438 | 70736.99004948139 | 161.50 | Standard Market |
| MS | campo grande | 315 | 65520.08040642738 | 208.00 | Standard Market |
| MA | sao luis | 345 | 63114.89991879463 | 182.94 | Standard Market |
| PB | joao pessoa | 253 | 62606.56971311569 | 247.46 | Standard Market |
| ES | vitoria | 376 | 62057.10984182358 | 165.05 | Standard Market |
| RJ | sao goncalo | 405 | 61570.400188207626 | 152.03 | Standard Market |
| PI | teresina | 278 | 60322.97010374069 | 216.99 | Standard Market |
| SP | piracicaba | 363 | 58216.87995111942 | 160.38 | Standard Market |
| SP | barueri | 425 | 58004.639814246446 | 136.48 | Standard Market |
| SP | mogi das cruzes | 377 | 57979.230025827885 | 153.79 | Standard Market |
| MG | contagem | 419 | 57814.660032749176 | 137.98 | Standard Market |
| MG | uberlandia | 372 | 56786.0901248306 | 152.65 | Standard Market |
| ES | vila velha | 329 | 55557.45991837978 | 168.87 | Standard Market |
| SP | sao jose do rio preto | 332 | 53719.34991595149 | 161.81 | Standard Market |
| AL | maceio | 246 | 53101.38010084629 | 215.86 | Standard Market |
| PR | londrina | 302 | 53029.720022678375 | 175.60 | Standard Market |
| SP | maua | 319 | 48421.219797849655 | 151.79 | Standard Market |
| MT | cuiaba | 248 | 47117.16004541516 | 189.99 | Standard Market |
| SP | bauru | 269 | 44903.49977505207 | 166.93 | Standard Market |
| PR | maringa | 264 | 44655.54022991657 | 169.15 | Standard Market |
| SE | aracaju | 220 | 44598.79984438419 | 202.72 | Standard Market |
| RS | caxias do sul | 223 | 44111.57005023956 | 197.81 | Standard Market |
| SP | praia grande | 304 | 44072.049874305725 | 144.97 | Standard Market |
| ES | serra | 285 | 42965.76991789043 | 150.76 | Standard Market |
| RN | natal | 205 | 42851.00978708267 | 209.03 | Standard Market |
| SP | indaiatuba | 277 | 41590.47012972832 | 150.15 | Standard Market |
| SC | joinville | 262 | 40905.22002220154 | 156.13 | Standard Market |
| RJ | duque de caxias | 263 | 39908.03999757767 | 151.74 | Standard Market |
| RJ | campos dos goytacazes | 237 | 39898.530123472214 | 168.35 | Standard Market |
| SP | taboao da serra | 288 | 39766.34001151472 | 138.08 | Standard Market |
| RJ | petropolis | 237 | 39532.84000623226 | 166.81 | Standard Market |
| MG | divinopolis | 134 | 38727.710107803345 | 289.01 | Standard Market |
| RJ | volta redonda | 228 | 38645.94992351532 | 169.50 | Standard Market |
| RJ | macae | 236 | 37543.26006150246 | 159.08 | Standard Market |
| SP | marilia | 196 | 37493.970249176025 | 191.30 | Standard Market |
| RS | santa maria | 194 | 37224.64966106415 | 191.88 | Standard Market |
| SP | carapicuiba | 324 | 37196.800077438354 | 114.80 | Standard Market |
| SP | sao caetano do sul | 274 | 36571.90995502472 | 133.47 | Standard Market |
| SP | cotia | 247 | 34772.90995979309 | 140.78 | Standard Market |
| SP | taubate | 266 | 34560.32997727394 | 129.93 | Standard Market |
| MG | betim | 201 | 34349.920018196106 | 170.90 | Standard Market |
| SP | sao carlos | 231 | 33906.410032749176 | 146.78 | Standard Market |
| SP | guaruja | 224 | 33690.860169410706 | 150.41 | Standard Market |
| SP | diadema | 282 | 33675.98999106884 | 119.42 | Standard Market |
| BA | feira de santana | 185 | 32466.80003336072 | 175.50 | Standard Market |
| RS | canoas | 209 | 31982.830045431852 | 153.03 | Standard Market |
| MG | uberaba | 187 | 31911.67006677389 | 170.65 | Standard Market |
| MG | montes claros | 209 | 31283.009807288647 | 149.68 | Standard Market |
| RJ | nova friburgo | 148 | 31206.370090961456 | 210.85 | Standard Market |
| SP | presidente prudente | 160 | 29916.460077762604 | 186.98 | Standard Market |
| SC | blumenau | 186 | 29206.580057948828 | 157.02 | Standard Market |
| SP | suzano | 232 | 29022.78001856804 | 125.10 | Standard Market |
| SP | americana | 219 | 28545.730053901672 | 130.35 | Standard Market |
| PR | cascavel | 148 | 27649.599861621857 | 186.82 | Standard Market |
| RS | pelotas | 184 | 27356.58004850149 | 148.68 | Standard Market |
| SP | limeira | 187 | 26206.299997091293 | 140.14 | Standard Market |
| RO | porto velho | 109 | 26121.920029640198 | 239.65 | Standard Market |
| SP | santana de parnaiba | 180 | 26074.63006234169 | 144.86 | Standard Market |
| MG | ipatinga | 170 | 26003.559985399246 | 152.96 | Standard Market |
| AM | manaus | 139 | 25793.0799767375 | 185.56 | Standard Market |
| SP | franca | 158 | 25736.110070228577 | 162.89 | Standard Market |
| SP | valinhos | 182 | 25607.430002212524 | 140.70 | Standard Market |
| PE | jaboatao dos guararapes | 133 | 25458.900188446045 | 191.42 | Standard Market |
| SP | sumare | 179 | 24509.429921627045 | 136.92 | Standard Market |
| SC | sao jose | 168 | 24347.42995071411 | 144.93 | Standard Market |
| MG | pouso alegre | 131 | 24195.410016059875 | 184.70 | Standard Market |
| SP | atibaia | 157 | 23783.42003250122 | 151.49 | Standard Market |
| RJ | rio das ostras | 135 | 23584.38001394272 | 174.70 | Standard Market |
| MG | nova lima | 98 | 23287.82988166809 | 237.63 | Standard Market |
| SP | rio claro | 152 | 23181.3299202919 | 152.51 | Standard Market |
| SP | araraquara | 153 | 23106.97009086609 | 151.03 | Standard Market |
| RJ | barra mansa | 120 | 22938.179938793182 | 191.15 | Standard Market |
| SP | embu das artes | 162 | 22846.049993515015 | 141.02 | Standard Market |
| PB | campina grande | 68 | 22783.29009628296 | 335.05 | Standard Market |
| SP | braganca paulista | 144 | 22683.220050811768 | 157.52 | Standard Market |
| MG | governador valadares | 135 | 22368.88001060486 | 165.70 | Standard Market |
| SP | sao vicente | 161 | 22237.13000050187 | 138.12 | Standard Market |
| PR | ponta grossa | 142 | 22152.279952526093 | 156.00 | Standard Market |
| RJ | sao joao de meriti | 131 | 21932.93999648094 | 167.43 | Standard Market |
| TO | palmas | 90 | 21790.370041251183 | 242.12 | Standard Market |
| RS | gravatai | 112 | 21719.35986328125 | 193.92 | Standard Market |
| SP | itaquaquecetuba | 170 | 21716.27007201314 | 127.74 | Standard Market |
| RJ | angra dos reis | 84 | 21567.900049209595 | 256.76 | Standard Market |
| SC | itajai | 119 | 21465.519989013672 | 180.38 | Standard Market |
| PA | ananindeua | 88 | 21236.850120782852 | 241.33 | Standard Market |
| SP | itapevi | 170 | 21190.409993935376 | 124.65 | Standard Market |
| SP | jacarei | 191 | 21113.10000383854 | 110.54 | Standard Market |
| ES | cariacica | 138 | 20593.749937057495 | 149.23 | Standard Market |
| RS | novo hamburgo | 121 | 20527.589955329895 | 169.65 | Standard Market |
| RJ | teresopolis | 119 | 20266.340026408434 | 170.31 | Standard Market |
| MG | sete lagoas | 127 | 20239.31993675232 | 159.36 | Standard Market |
| GO | anapolis | 111 | 20029.820016860962 | 180.45 | Standard Market |
| RJ | cabo frio | 114 | 19568.42012345791 | 171.65 | Standard Market |
| SP | aracatuba | 140 | 19530.12003302574 | 139.50 | Standard Market |
| MG | pocos de caldas | 118 | 19415.190086126328 | 164.54 | Standard Market |
| SC | balneario camboriu | 99 | 19358.679819107056 | 195.54 | Standard Market |
| MG | patos de minas | 100 | 19349.550039052963 | 193.50 | Standard Market |
| RS | rio grande | 123 | 19338.510021209717 | 157.22 | Standard Market |
| BA | vitoria da conquista | 88 | 19252.20994949341 | 218.78 | Standard Market |
| RJ | araruama | 77 | 19196.049936294556 | 249.30 | Standard Market |
| ES | cachoeiro de itapemirim | 121 | 19175.44999051094 | 158.47 | Standard Market |
| SP | botucatu | 101 | 19053.070067703724 | 188.64 | Standard Market |
| SP | paulinia | 129 | 18790.840075671673 | 145.67 | Standard Market |
| SP | hortolandia | 145 | 18748.569893836975 | 129.30 | Standard Market |
| RJ | mage | 110 | 18679.999910354614 | 169.82 | Standard Market |
| MG | vicosa | 89 | 18649.7098236084 | 209.55 | Standard Market |
| RJ | marica | 137 | 18511.419981002808 | 135.12 | Standard Market |
| RS | passo fundo | 112 | 18088.809967041016 | 161.51 | Standard Market |
| SC | criciuma | 92 | 17812.22989654541 | 193.61 | Standard Market |
| PR | sao jose dos pinhais | 131 | 17763.43998658657 | 135.60 | Standard Market |
| SC | chapeco | 102 | 17607.440014123917 | 172.62 | Standard Market |
| SP | ferraz de vasconcelos | 110 | 17471.239877700806 | 158.83 | Standard Market |
| GO | aparecida de goiania | 109 | 16962.150075912476 | 155.62 | Standard Market |
| PE | petrolina | 65 | 16959.21994781494 | 260.91 | Standard Market |
| AC | rio branco | 70 | 16928.469888687134 | 241.84 | Standard Market |
| SP | birigui | 78 | 16626.830087661743 | 213.16 | Standard Market |
| SP | guaratingueta | 96 | 16593.199988663197 | 172.85 | Standard Market |
| MG | itajuba | 94 | 16505.20000600815 | 175.59 | Standard Market |
| RJ | resende | 117 | 16496.71998155117 | 141.00 | Standard Market |
| RJ | belford roxo | 110 | 16281.119910791516 | 148.01 | Standard Market |
| MG | varginha | 88 | 16022.510070800781 | 182.07 | Standard Market |
| RJ | nilopolis | 106 | 15881.68000793457 | 149.83 | Standard Market |
| PE | olinda | 93 | 15650.040005683899 | 168.28 | Standard Market |
| SC | jaragua do sul | 89 | 15357.909955978394 | 172.56 | Standard Market |
| MG | lavras | 83 | 15307.959968531504 | 184.43 | Standard Market |
| SP | araras | 94 | 15187.249944269657 | 161.57 | Standard Market |
| SP | caraguatatuba | 86 | 15082.739949911833 | 175.38 | Standard Market |
| MG | araxa | 75 | 15041.850039482117 | 200.56 | Standard Market |
| SP | santa barbara d’oeste | 118 | 14980.129915863276 | 126.95 | Standard Market |
| MG | ribeirao das neves | 99 | 14890.069915771484 | 150.40 | Standard Market |
| SP | caieiras | 98 | 14729.870056152344 | 150.30 | Standard Market |
| SP | itu | 132 | 14614.819989204407 | 110.72 | Standard Market |
| SP | pindamonhangaba | 100 | 14375.700001001358 | 143.76 | Standard Market |
| SP | ourinhos | 77 | 14325.329902648926 | 186.04 | Standard Market |
| MG | barbacena | 80 | 14321.699979782104 | 179.02 | Standard Market |
| MT | rondonopolis | 65 | 14105.620091438293 | 217.01 | Standard Market |
| SP | itapetininga | 77 | 14048.460102081299 | 182.45 | Standard Market |
| ES | linhares | 64 | 13987.340067327023 | 218.55 | Standard Market |
| SP | mogi-guacu | 91 | 13972.309995651245 | 153.54 | Standard Market |
| PR | foz do iguacu | 87 | 13902.670015335083 | 159.80 | Standard Market |
| SP | assis | 84 | 13819.309928894043 | 164.52 | Standard Market |
| AP | macapa | 54 | 13666.030033111572 | 253.07 | Standard Market |
| SP | itatiba | 97 | 13634.020051956177 | 140.56 | Standard Market |
| SC | lages | 83 | 13616.230019569397 | 164.05 | Standard Market |
| SP | sao joao da boa vista | 81 | 13608.180032730103 | 168.00 | Standard Market |
| MG | santa luzia | 91 | 13575.690139114857 | 149.18 | Standard Market |
| CE | sobral | 35 | 13295.730205535889 | 379.88 | Standard Market |
| RS | sao leopoldo | 104 | 13291.570051595569 | 127.80 | Standard Market |
| SC | palhoca | 93 | 13273.769969940186 | 142.73 | Standard Market |
| SP | amparo | 66 | 13001.819974184036 | 197.00 | Standard Market |
| BA | barreiras | 52 | 12952.729969024658 | 249.09 | Standard Market |
| SP | tatui | 73 | 12815.720006942749 | 175.56 | Standard Market |
| MG | itabira | 79 | 12748.300029754639 | 161.37 | Standard Market |
| SP | varzea paulista | 78 | 12659.479978561401 | 162.30 | Standard Market |
| PE | caruaru | 64 | 12579.229939937592 | 196.55 | Standard Market |
| MG | muriae | 63 | 12532.070067167282 | 198.92 | Standard Market |
| SP | itanhaem | 79 | 12338.11986541748 | 156.18 | Standard Market |
| SP | salto | 93 | 12137.629947304726 | 130.51 | Standard Market |
| SC | tubarao | 60 | 12130.980094909668 | 202.18 | Standard Market |
| SP | votorantim | 84 | 12085.639886379242 | 143.88 | Standard Market |
| MG | araguari | 54 | 12048.940017700195 | 223.13 | Standard Market |
| ES | guarapari | 67 | 12021.139976501465 | 179.42 | Standard Market |
| RS | santa cruz do sul | 62 | 11974.649991989136 | 193.14 | Standard Market |
| SP | franco da rocha | 109 | 11893.329976558685 | 109.11 | Standard Market |
| GO | rio verde | 64 | 11847.880012512207 | 185.12 | Standard Market |
| SP | ribeirao pires | 107 | 11780.649990081787 | 110.10 | Standard Market |
| PR | toledo | 70 | 11688.66003036499 | 166.98 | Standard Market |
| BA | porto seguro | 39 | 11671.599877357483 | 299.27 | Standard Market |
| SC | gaspar | 29 | 11602.949851989746 | 400.10 | Standard Market |
| SP | cacapava | 73 | 11520.139964461327 | 157.81 | Standard Market |
| SP | cajamar | 98 | 11515.510002374649 | 117.51 | Standard Market |
| GO | jatai | 54 | 11337.930023908615 | 209.96 | Standard Market |
| BA | lauro de freitas | 75 | 11278.609934806824 | 150.38 | Standard Market |
| MG | caratinga | 62 | 11211.449956178665 | 180.83 | Standard Market |
| MG | conselheiro lafaiete | 84 | 11192.38003563881 | 133.24 | Standard Market |
| SP | catanduva | 74 | 11183.029972076416 | 151.12 | Standard Market |
Insights:
- The Dominance of São Paulo (SP): São Paulo completely crushes the competition. It acts as our absolute major economic hub, pulling in $2.15M in revenue from over 15,000 orders. This single city brings in almost double the revenue of the second-place city, Rio de Janeiro.
- Top 5 Revenue Centers: The top 5 regions driving the highest total revenue are all major state capitals: São Paulo (SP), Rio de Janeiro (RJ), Belo Horizonte (MG), Brasília (DF), and Curitiba (PR). Together, they represent the core market for Olist.
- State Performance (The “SP” Factor): Even outside of the main capital, the state of São Paulo (SP) is dominant. Cities like Campinas, Guarulhos, and Santos pull in massive volumes, showing that the platform’s logistics and marketing are incredibly effective throughout this entire state.
- High Volume vs. High Revenue Outliers:
- High Average Order Value (AOV) in Remote Regions: If you look at standard markets like Belém (PA), João Pessoa (PB), or Macapá (AP), their order volumes are lower (under 500 orders), but their Average Order Values are huge (247, and $253 respectively). Customers in these regions are likely buying heavier, more expensive items because local retail options are limited.
- Volume Does Not Always Equal Value: Take Carapicuiba (SP) as an example. It generated 324 orders (higher than many standard markets), but only pulled in 114.80. This tells us the city generates high engagement but mostly for cheaper items.
Average Order Value and Basket Size Analysis
10. AOV and Busket Size Analysis: What is the average order value (AOV) and average basket size (number of items per order) for Olist? How do these metrics vary across year and months?
Solution:
-
Firstly, we isolate order-level totals (
order_item_totalsandorder_payment_totalsCTEs): This is crucial to prevent data duplication caused by 1-to-many relationships (multiple items or payment methods per order). We calculate the total number of items (items_in_basket) and the total payment value (total_order_payment) grouped strictly by uniqueorder_id. -
Secondly, we aggregate these metrics by month (
monthly_metricsCTE): We join our safe order-level totals with theordersandCalendartables, ensuring we filter out ‘canceled’ or ‘unavailable’ orders. This gives us the absolutetotal_orders,monthly_revenue, andmonthly_items_countfor each specific year and month. -
Finally, we calculate the key performance indicators (Final
SELECT): By dividing the monthly revenue by total orders, we get the Average Order Value (AOV). Dividing the total items by total orders gives us the Average Basket Size. We also calculate anavg_price_per_itemproxy (AOV divided by basket size) to understand the value density of the baskets over time.
Show SQL Code
with order_item_totals as (
-- step 1: calculate total items and total price per order
-- this prevents duplication before joining with payments
select
order_id,
count(order_item_id) as items_in_basket,
sum(price) as total_items_price
from
order_items
group by
order_id
),
order_payment_totals as (
-- step 2: calculate total payment value per order
-- (accounts for multi-payment methods/installments)
select
order_id,
sum(payment_value) as total_order_payment
from
payments
group by
order_id
),
monthly_metrics as (
-- step 3: aggregate metrics by month
select
c.year,
c.month_number,
c.month_name,
count(o.order_id) as total_orders,
sum(p.total_order_payment) as monthly_revenue,
sum(i.items_in_basket) as monthly_items_count
from
orders o
inner join
Calendar c on o.purchase_datekey = c.datekey
inner join
order_item_totals i on o.order_id = i.order_id
inner join
order_payment_totals p on o.order_id = p.order_id
where
o.order_status not in ('canceled', 'unavailable')
group by
c.year, c.month_number, c.month_name
)
-- final output: calculating aov and avg basket size trends
select
year,
month_name,
total_orders,
-- aov: total revenue / total orders
cast(monthly_revenue / total_orders as decimal(10,2)) as aov,
-- avg basket size: total items / total orders
cast(monthly_items_count * 1.0 / total_orders as decimal(10,2)) as avg_basket_size,
-- item value proxy: aov / avg basket size (average price per item)
cast((monthly_revenue / total_orders) / (monthly_items_count * 1.0 / total_orders) as decimal(10,2)) as avg_price_per_item
from
monthly_metrics
order by
year, month_number;
Results:
| year | month_name | total_orders | aov | avg_basket_size | avg_price_per_item |
|---|---|---|---|---|---|
| 2016 | September | 1 | 136.23 | 2.00 | 68.11 |
| 2016 | October | 290 | 177.35 | 1.18 | 150.38 |
| 2016 | December | 1 | 19.62 | 1.00 | 19.62 |
| 2017 | January | 787 | 174.09 | 1.21 | 143.76 |
| 2017 | February | 1718 | 165.09 | 1.13 | 146.50 |
| 2017 | March | 2617 | 162.65 | 1.14 | 143.08 |
| 2017 | April | 2377 | 170.80 | 1.12 | 152.63 |
| 2017 | May | 3640 | 160.14 | 1.13 | 141.97 |
| 2017 | June | 3205 | 155.95 | 1.11 | 139.97 |
| 2017 | July | 3946 | 146.70 | 1.14 | 128.84 |
| 2017 | August | 4272 | 154.98 | 1.14 | 135.61 |
| 2017 | September | 4227 | 169.67 | 1.14 | 148.95 |
| 2017 | October | 4547 | 168.20 | 1.17 | 144.30 |
| 2017 | November | 7421 | 157.98 | 1.16 | 135.91 |
| 2017 | December | 5618 | 153.37 | 1.12 | 136.77 |
| 2018 | January | 7187 | 153.42 | 1.14 | 134.91 |
| 2018 | February | 6624 | 147.92 | 1.15 | 128.98 |
| 2018 | March | 7168 | 160.82 | 1.14 | 140.66 |
| 2018 | April | 6919 | 167.12 | 1.15 | 145.32 |
| 2018 | May | 6833 | 167.68 | 1.16 | 145.07 |
| 2018 | June | 6145 | 166.07 | 1.15 | 144.55 |
| 2018 | July | 6233 | 166.83 | 1.13 | 147.73 |
| 2018 | August | 6421 | 155.26 | 1.12 | 138.15 |
| 2018 | September | 1 | 166.46 | 1.00 | 166.46 |
İnsights:
- Single-Item Shoppers: The most striking takeaway is the average basket size. It stays completely flat, hovering between 1.11 and 1.17 items per order across all active months. Olist customers almost exclusively buy just one item at a time.
- Stable Average Order Value (AOV): AOV is remarkably consistent, generally floating between 170. There are slight dips (like 147.92 in Feb 2018), but it always bounces back into the $160s quickly.
- The Black Friday Shopping Behavior: During the massive sales peak in November 2017, the AOV ($157.98) and basket size (1.16) were completely average. This proves the Black Friday revenue boom came entirely from a massive flood of new orders, not from customers stuffing their carts with multiple discounted items.
- Price Per Item Controls AOV: Because the basket size is practically stuck at 1, the AOV is directly controlled by the
avg_price_per_item. When customers buy slightly cheaper goods overall (like in early 2018), the AOV drops right alongside it.
Conclusion
What We Did:
- Analyzed overall order and revenue trends using both raw monthly groupings and a 3-month rolling average to smooth out volatility.
- Segmented product categories to compare raw sales volume against actual revenue generated.
- Mapped out the geographic distribution of sales to find high-performing states and cities.
- Tracked Average Order Value (AOV) and average basket size across the entire timeline.
What We Obtained (Key Findings):
- Growth & Plateau: Olist experienced explosive growth in 2017 and matured into a stable business in 2018, consistently generating between 1.15M monthly.
- Single-Item Baskets: Customers are overwhelmingly single-item shoppers. The average basket size is practically locked at ~1.14 items across all months.
- Volume Over Cart Size: The massive Black Friday peak in November 2017 was driven entirely by a flood of new orders, not by customers stuffing more items into their carts.
- The São Paulo Anchor: São Paulo (SP) is the undisputed core market for volume and revenue. However, remote regions consistently show a higher AOV, likely due to a lack of local retail alternatives.
- Category Efficiency: Categories like health/beauty and watches are highly efficient (high volume + high revenue). In contrast, electronics are a “trap” category, moving lots of units but yielding relatively low revenue.