Weighted Average in SQL

A weighted average gives each value an importance, such as quantity, so a price on 1,000 units counts for more than a price on 10.

Example query

This example assumes: order_items(id, product_id bigint, unit_price numeric, quantity numeric). It is written in PostgreSQL syntax, and your table and column names will differ from these.

SELECT product_id,
       SUM(unit_price * quantity) / NULLIF(SUM(quantity), 0) AS weighted_avg_price,
       AVG(unit_price) AS simple_avg_price,
       SUM(quantity) AS units
FROM order_items
GROUP BY product_id
ORDER BY units DESC;

How it works

  • Multiplying each price by its quantity and summing gives total revenue for the product.
  • Dividing by total quantity gives the average price actually received per unit.
  • The simple AVG(unit_price) treats a 1-unit order and a 1,000-unit order equally, which is why the two numbers differ.

MySQL, BigQuery, SQL Server and SQLite differences

  • Standard SQL; the same expression works in every major database.

Common mistakes

  • Averaging a pre-computed average (for example, average price per day) is not a weighted average; go back to the underlying rows.
  • Weights of zero or null drop rows; check how many rows contribute.
  • Discounts that are stored separately from unit_price must be applied before weighting.

Ask for it in plain English

Instead of writing the query yourself, you can type the question. SchemaChat turns it into SQL against your connected database or uploaded file, runs it, and shows the SQL and the figures it used so you can check the answer before you share it. Check that the query matches the definition your business uses.

  • What is the average selling price per product, weighted by quantity?
  • Compare the simple and weighted average discount by region.

Frequently asked questions

What is weighted average in SQL?
A weighted average gives each value an importance, such as quantity, so a price on 1,000 units counts for more than a price on 10.
How does the weighted average query work?
Multiplying each price by its quantity and summing gives total revenue for the product. Dividing by total quantity gives the average price actually received per unit. The simple AVG(unit_price) treats a 1-unit order and a 1,000-unit order equally, which is why the two numbers differ.
What commonly goes wrong with weighted average in SQL?
Averaging a pre-computed average (for example, average price per day) is not a weighted average; go back to the underlying rows.