(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisbon

How to calculate inventory turnover in DAX: step by step

João Barros 22 de October de 2026 5 min read

Let’s calculate inventory turnover in DAX to measure how many times inventory is sold within a period. This metric helps assess stock efficiency, detect excess or stockouts and support replenishment and price-setting decisions. Practically, higher turnover usually indicates the business is converting stock into sales quickly; very low turnover can reveal excess stock or slow-moving products.

Prerequisites

  • Power BI Desktop with a simple model: Sales and Inventory tables and a Date table. E.g.: Sales with columns Sales[SalesAmount], Sales[COGS], Sales[Date], Sales[ProductID]; Inventory with Inventory[StockValue], Inventory[Date], Inventory[ProductID].
  • Relationships: Sales[Date] -> Date[Date]; Inventory[Date] -> Date[Date]; Sales[ProductID] -> Inventory[ProductID]. Ensure the Date table is marked as Date table for Time Intelligence to work.
  • Basic DAX knowledge: measures, CALCULATE, SUM, AVERAGE and FILTER. It is ideal to also be aware of granularity levels (by product, by day, by month).

Step 1: Understand the inventory turnover formula

Inventory turnover (Inventory Turnover) is typically = Cost of Goods Sold (COGS) / Average Inventory. If you don’t have COGS, you can use Sales (Revenue) as a proxy — noting that this changes the interpretation. Average Inventory is often the average between beginning and ending inventory for the period, or the daily average if there are daily records.

Practical example: if in one year Total COGS = €200,000 and Average Inventory = €50,000, then Inventory Turnover = 200,000 / 50,000 = 4. That is, the stock "turned over" 4 times that year. To convert to Days Inventory Outstanding (DIO): DIO = 365 / 4 = 91.25 days.

Step 2: Create base measures (Sales and COGS)

Start by creating measures for total sales and, if available, COGS. These measures serve as the numerator in the formula. Check units (currency) and ensure you are not summing duplicated values due to a model error.

Total Sales = SUM(Sales[SalesAmount])
Total COGS = SUM(Sales[COGS])

Best practices: use FORMAT only in visuals. Keep measures numeric without text so they can be used in subsequent calculations. If your COGS is in a separate table, create relationships or use CALCULATE with USERELATIONSHIP if necessary.

Step 3: Create daily or period-end inventory measure

If the Inventory table has daily records per product, it’s preferable to calculate the daily Average Inventory. If you only have monthly snapshots, you can use the stock on the last day of the month (closing stock).

Closing Inventory =
CALCULATE(
    SUM(Inventory[StockValue]),
    LASTDATE(Date[Date])
)

This measure returns the stock on the last day of the filter context (month, quarter, etc.). E.g.: in the context of March, if the last recorded day is 03/31 and the total stock is €120,000, Closing Inventory = €120,000.

Step 4: Simple Average Inventory measure (beginning + end)

If you have daily stock records, calculate Average Inventory as the average of daily inventory in the period via AVERAGEX over days. This gives a more stable estimate, especially when there are significant daily variations.

Average Inventory (Daily) =
AVERAGEX(
    VALUES(Date[Date]),
    CALCULATE(SUM(Inventory[StockValue]))
)

Example: if during a month the daily total stock values are 40k, 42k, 38k, … the daily average might be around 41k. For monthly periods, this average is more representative than just the closing stock.

Step 5: Inventory turnover measure (with COGS)

Now combine the measures: turnover = COGS / Average Inventory. Use DIVIDE to avoid division by zero and to control the value returned when the denominator is zero.

Inventory Turnover =
DIVIDE(
    [Total COGS],
    [Average Inventory (Daily)],
    BLANK()
)

-- If using Closing Inventory as a proxy:
Inventory Turnover (Closing) =
DIVIDE(
    [Total COGS],
    [Closing Inventory],
    BLANK()
)

Numerical example: Total COGS (month) = €50,000, Average Inventory (Daily) = €12,500 → Inventory Turnover = 4. If the denominator is zero, DIVIDE returns BLANK() by default; you can substitute with 0 if you prefer.

Step 6: Period adjustments and comparisons (e.g., yearly or monthly)

Turnover is usually calculated annually or monthly. Use the Date table and Time Intelligence functions to compare periods. For example, use TOTALYTD to sum COGS up to year-to-date and compare with the average inventory for the corresponding period.

Total COGS YTD =
TOTALYTD([Total COGS], Date[Date])

Inventory Turnover YTD =
DIVIDE(
    [Total COGS YTD],
    [Average Inventory (Daily)],
    BLANK()
)

Also consider calculating moving averages (3 months, 12 months) to smooth seasonality. E.g.: a 12-month moving average turnover will be less sensitive to seasonal sales spikes.

Verify the result

Create a table visual in Power BI with Date[Year] or Date[Month] and the measures: Total COGS, Average Inventory (Daily) and Inventory Turnover. Check whether the values make sense: very high turnover (>12) can indicate insufficient stock (e.g., fast retail like supermarkets has high values), moderate turnover (3–6) is common in electronics, and very low (<1) indicates excess stock (e.g., furniture tends to have low values). Test with filters by ProductID to confirm per product. If a product has Inventory Turnover of 0, investigate the data in Inventory or the relationship between tables.

Conclusion

After implementing these measures you can compare turnover by period, product or category and make decisions about replenishment, pricing and promotions. Next steps: adjust the Inventory Average to a sales-weighted average, calculate Days Inventory Outstanding (DIO = 365 / Turnover) or set up alerts when turnover falls below a threshold. Practical tip: always use DIVIDE to avoid division-by-zero errors and validate assumptions about COGS vs Revenue — if you use Revenue as a proxy, document the limitation, because differing margins affect the interpretation.