Recipe Tableau and SQL

Which few products make most of your revenue?

Total revenue per product, sort from largest to smallest, and divide the running total by the grand total. In this store, 12 of 40 products (30%) make 80% of revenue: not quite 80/20, which is normal.

Updated

The data

Kettle & Burr coffee-gear store, orders in 2025

Synthetic dataorders.csv

A small online store selling 40 products: brewers, grinders, kettles, beans and accessories. 1,200 orders in 2025.

order_idorder_dateproductcategoryquantityrevenue
O-109462025-01-01Paper Filters 100Filters & Care113.76
O-103042025-01-02AeroPress GoBrewers161.55
O-106572025-01-02Ethiopia Yirgacheffe 250gBeans358.68
O-109122025-01-02Ethiopia Yirgacheffe 250gBeans119.56

Step 1

Total each product

Each bar is one product's total for the year. A few tall bars, then a long tail: that shape is what Pareto analysis measures.

Tableau

SUM([revenue])

The xmetric engine ran this formula and got the SQL’s Revenue column, row for row.

SQL

SELECT product, SUM(revenue) AS total
FROM input
GROUP BY product

Rows

ProductRevenue
AeroPress Go$11,264
Ethiopia Yirgacheffe 250g$11,032
Burr Grinder Pro$8,964
Gooseneck Kettle Electric$7,921
Paper Filters 100$2,119
Pour-Over Dripper$1,734
House Espresso 1kg$1,664
Travel Tumbler$1,585
Grinder Brush Set$1,555
Tamper 58mm$1,510
Hand Grinder Mini$1,453
Gooseneck Kettle Stovetop$1,286
Coaster Set$1,219
Clever Dripper$966
Kenya AA 250g$962
Burr Grinder Lite$953
Milk Frother$751
Decaf Swiss Water 250g$739
Siphon Brewer$685
Glass Server 600ml$644
Coffee Scale$536
French Press 1L$514
Chemex 8-Cup$464
Storage Canister$459
Cold Brew Jar$420
Moka Pot 6-Cup$363
Filter Holder$361
Cloth Filter 2-Pack$322
Ceramic Mug$284
Guatemala Antigua 250g$260
Colombia Huila 250g$255
Travel Kettle$219
Gift Card 50$163
Knock Box$134
Barista Apron$132
Latte Art Pitcher$108
Cleaning Tablets$101
Brazil Santos 1kg$86
Seasonal Single Origin 250g$71
Descaler$70

Step 2

Add up from the top

The line is the share of the year's total covered so far. Compute it in descending order of the bars; in Tableau, set Compute Using to product and sort product by the measure, descending.

Tableau

RUNNING_SUM(SUM([revenue])) / TOTAL(SUM([revenue]))

SQL

WITH t AS (
  SELECT product, SUM(revenue) AS total
  FROM input
  GROUP BY product
)
SELECT
  product,
  total,
  SUM(total) OVER (ORDER BY total DESC, product ROWS UNBOUNDED PRECEDING)
    / SUM(total) OVER () AS cumulative_share
FROM t
ORDER BY total DESC, product

Rows

ProductRevenueCumulative share
AeroPress Go$11,26417.5%
Ethiopia Yirgacheffe 250g$11,03234.7%
Burr Grinder Pro$8,96448.6%
Gooseneck Kettle Electric$7,92160.9%
Paper Filters 100$2,11964.2%
Pour-Over Dripper$1,73466.9%
House Espresso 1kg$1,66469.5%
Travel Tumbler$1,58572%
Grinder Brush Set$1,55574.4%
Tamper 58mm$1,51076.7%
Hand Grinder Mini$1,45379%
Gooseneck Kettle Stovetop$1,28681%
Coaster Set$1,21982.9%
Clever Dripper$96684.4%
Kenya AA 250g$96285.9%
Burr Grinder Lite$95387.3%
Milk Frother$75188.5%
Decaf Swiss Water 250g$73989.7%
Siphon Brewer$68590.7%
Glass Server 600ml$64491.7%
Coffee Scale$53692.6%
French Press 1L$51493.4%
Chemex 8-Cup$46494.1%
Storage Canister$45994.8%
Cold Brew Jar$42095.4%
Moka Pot 6-Cup$36396%
Filter Holder$36196.6%
Cloth Filter 2-Pack$32297.1%
Ceramic Mug$28497.5%
Guatemala Antigua 250g$26097.9%
Colombia Huila 250g$25598.3%
Travel Kettle$21998.7%
Gift Card 50$16398.9%
Knock Box$13499.1%
Barista Apron$13299.3%
Latte Art Pitcher$10899.5%
Cleaning Tablets$10199.6%
Brazil Santos 1kg$8699.8%
Seasonal Single Origin 250g$7199.9%
Descaler$70100%

Step 3

Turn products into a share too

With both axes as shares, any dataset fits the same square. Where the curve crosses the cutoff line, read off the share of products that got you there.

Tableau

INDEX() / SIZE()

SQL

WITH t AS (
  SELECT product, SUM(revenue) AS total
  FROM input
  GROUP BY product
), r AS (
  SELECT
    product,
    total,
    ROW_NUMBER() OVER (ORDER BY total DESC, product) AS k,
    COUNT(*) OVER () AS n,
    SUM(total) OVER (ORDER BY total DESC, product ROWS UNBOUNDED PRECEDING)
      / SUM(total) OVER () AS cumulative_share
  FROM t
)
SELECT product, k * 1.0 / n AS product_share, cumulative_share
FROM r
ORDER BY k

Rows

ProductProduct shareCumulative share
AeroPress Go2.5%17.5%
Ethiopia Yirgacheffe 250g5%34.7%
Burr Grinder Pro7.5%48.6%
Gooseneck Kettle Electric10%60.9%
Paper Filters 10012.5%64.2%
Pour-Over Dripper15%66.9%
House Espresso 1kg17.5%69.5%
Travel Tumbler20%72%
Grinder Brush Set22.5%74.4%
Tamper 58mm25%76.7%
Hand Grinder Mini27.5%79%
Gooseneck Kettle Stovetop30%81%
Coaster Set32.5%82.9%
Clever Dripper35%84.4%
Kenya AA 250g37.5%85.9%
Burr Grinder Lite40%87.3%
Milk Frother42.5%88.5%
Decaf Swiss Water 250g45%89.7%
Siphon Brewer47.5%90.7%
Glass Server 600ml50%91.7%
Coffee Scale52.5%92.6%
French Press 1L55%93.4%
Chemex 8-Cup57.5%94.1%
Storage Canister60%94.8%
Cold Brew Jar62.5%95.4%
Moka Pot 6-Cup65%96%
Filter Holder67.5%96.6%
Cloth Filter 2-Pack70%97.1%
Ceramic Mug72.5%97.5%
Guatemala Antigua 250g75%97.9%
Colombia Huila 250g77.5%98.3%
Travel Kettle80%98.7%
Gift Card 5082.5%98.9%
Knock Box85%99.1%
Barista Apron87.5%99.3%
Latte Art Pitcher90%99.5%
Cleaning Tablets92.5%99.6%
Brazil Santos 1kg95%99.8%
Seasonal Single Origin 250g97.5%99.9%
Descaler100%100%
50%95%

Step 4

Label the A, B and C products

A products carry the business, B products support it, C products are the tail. The product that crosses the cutoff is the first B product; some teams count it as A.

Tableau

IF RUNNING_SUM(SUM([revenue])) / TOTAL(SUM([revenue])) <= 0.8 THEN "A"
ELSEIF RUNNING_SUM(SUM([revenue])) / TOTAL(SUM([revenue])) <= 0.95 THEN "B"
ELSE "C"
END

SQL

WITH t AS (
  SELECT product, SUM(revenue) AS total
  FROM input
  GROUP BY product
), r AS (
  SELECT
    product,
    total,
    SUM(total) OVER (ORDER BY total DESC, product ROWS UNBOUNDED PRECEDING)
      / SUM(total) OVER () AS cumulative_share
  FROM t
)
SELECT
  product,
  total,
  CASE
    WHEN cumulative_share <= 0.8 THEN 'A'
    WHEN cumulative_share <= 0.95 THEN 'B'
    ELSE 'C'
    END AS segment
FROM r
ORDER BY total DESC, product

Rows

ProductRevenueSegment
AeroPress Go$11,264A
Ethiopia Yirgacheffe 250g$11,032A
Burr Grinder Pro$8,964A
Gooseneck Kettle Electric$7,921A
Paper Filters 100$2,119A
Pour-Over Dripper$1,734A
House Espresso 1kg$1,664A
Travel Tumbler$1,585A
Grinder Brush Set$1,555A
Tamper 58mm$1,510A
Hand Grinder Mini$1,453A
Gooseneck Kettle Stovetop$1,286B
Coaster Set$1,219B
Clever Dripper$966B
Kenya AA 250g$962B
Burr Grinder Lite$953B
Milk Frother$751B
Decaf Swiss Water 250g$739B
Siphon Brewer$685B
Glass Server 600ml$644B
Coffee Scale$536B
French Press 1L$514B
Chemex 8-Cup$464B
Storage Canister$459B
Cold Brew Jar$420C
Moka Pot 6-Cup$363C
Filter Holder$361C
Cloth Filter 2-Pack$322C
Ceramic Mug$284C
Guatemala Antigua 250g$260C
Colombia Huila 250g$255C
Travel Kettle$219C
Gift Card 50$163C
Knock Box$134C
Barista Apron$132C
Latte Art Pitcher$108C
Cleaning Tablets$101C
Brazil Santos 1kg$86C
Seasonal Single Origin 250g$71C
Descaler$70C

Is it always 80/20?

Almost never exactly. In this store 12 products, 30% of the range, make 80% of revenue. Move the slider: the share of products you need rises fast near the top, because the tail is long and each extra product adds little.

Common mistake

The running total follows the wrong order

If the running total adds products alphabetically, the curve no longer bends and the cutoff picks the wrong products. Sort by the measure, descending, before the running total.

WrongStarts with AeroPress Go, Barista Apron, Brazil Santos 1kg…
Point at the line to read it.
0%25%50%75%100%Products in this order →80%26 of 40

Tableau

RUNNING_SUM(SUM([revenue])) / TOTAL(SUM([revenue]))
// Compute Using: product, sorted A-Z

SQL

WITH t AS (
  SELECT product, SUM(revenue) AS total
  FROM input
  GROUP BY product
)
SELECT
  product,
  SUM(total) OVER (ORDER BY product ROWS UNBOUNDED PRECEDING)
    / SUM(total) OVER () AS cumulative_share
FROM t
ORDER BY product
RightStarts with AeroPress Go, Ethiopia Yirgacheffe 250g, Burr Grinder Pro…
Point at the line to read it.
0%25%50%75%100%Products in this order →80%12 of 40

Tableau

RUNNING_SUM(SUM([revenue])) / TOTAL(SUM([revenue]))
// Compute Using: product, sorted by SUM(revenue) descending

SQL

WITH t AS (
  SELECT product, SUM(revenue) AS total
  FROM input
  GROUP BY product
)
SELECT
  product,
  SUM(total) OVER (ORDER BY total DESC, product ROWS UNBOUNDED PRECEDING)
    / SUM(total) OVER () AS cumulative_share
FROM t
ORDER BY total DESC, product

Revenue or units?

Rank by the measure behind the decision. Switch Rank by to quantity and the picture changes: bags of beans sell the most units, while the Burr Grinder Pro, third by revenue, falls down the list.

Rank by
Point at the line to read it.
1AeroPress Go$11,2642Ethiopia Yirgacheffe 250g$11,0323Burr Grinder Pro$8,9644Gooseneck Kettle Electric$7,9215Paper Filters 100$2,1196Pour-Over Dripper$1,7347House Espresso 1kg$1,6648Travel Tumbler$1,5859Grinder Brush Set$1,55510Tamper 58mm$1,510
ABC

Common mistake

Ranking by units when the decision is about revenue

Switch Rank by to quantity: the coffee beans top the chart on units, while the Burr Grinder Pro drops from third. Rank by the measure you are deciding on.

Run it on your own data

Any export with an entity (product, customer, SKU) and a measure works, up to 100,000 rows. The panel below runs the whole file: it will sum revenue per product or customer, keep the positive totals, rank them and add both cumulative shares, ready to download as a CSV. It runs in your browser; nothing is uploaded.

How can I run Pareto analysis on my export?

Choose your CSV, drop it here or paste rows with headers. Match its columns to the analysis, and xmetric calculates the complete export in this browser. This panel accepts up to 100,000 rows; nothing is uploaded.

Definition. Sum values per entity; retain only positive entity totals; sort total descending with entity ascending as a tie-breaker. Cumulative entity share = 100 * row number / entity count. Cumulative value share = 100 * running sum / positive total. Worked result record · definition updated .

No own data loaded. Choose your export or try the labeled sample.

Questions

Does a Pareto analysis have to come out 80/20?

No. 80/20 is a rule of thumb, not a law. Real data lands anywhere from 60/20 to 95/10. The useful number is your own split, and how it moves when you change the cutoff.

Should I rank by revenue or by units?

Rank by the measure you are deciding on. Units and revenue rank products differently: in this store the most-sold product by units is not the top earner, and an expensive grinder ranks third by revenue on a small number of sales.

Why do I get a wrong curve in Tableau?

The running total must run in descending order of revenue. If Compute Using follows the product name instead, the curve climbs in alphabetical order and the cutoff lands on the wrong products.

Sources