Inventory Analytics with Power BI: Stock, Turnover, and Demand

Build Power BI inventory analytics dashboards covering stock levels, inventory turnover, ABC analysis, demand forecasting, and reorder point calculations with DAX formulas.

E
ECOSIRE Research and Development Team
|2026年3月19日6 分钟阅读1.2k 字数|

属于我们的Supply Chain & Procurement系列

阅读完整指南

使用 Power BI 进行库存分析:库存、周转率和需求

过剩库存每年的持有成本占其价值的 25-30%。缺货每年给零售商造成约 1 万亿美元的销售额损失。在这两个极端之间存在着最佳库存的狭窄范围,而 Power BI 是让运营团队精确遵循这条线的工具。

Power BI 中库存分析的挑战在于,库存是快照度量(我们现在有多少?),而不是流量度量(本月售出了多少?)。这种区别驱动着数据模型和每个 DAX 计算模式中的每个设计决策。本指南涵盖了完整的库存分析平台:数据模型、ABC 分类、周转分析、再订购点计算和需求预测可视化。

要点

  • 库存是一种时间点(快照)衡量指标,需要与销售指标不同的 DAX 模式
  • ABC 分析按收入贡献对项目进行分类:A(前 80%)、B(接下来 15%)、C(后 5%)
  • 库存周转率 = COGS / 平均库存 — 因行业而异
  • 再订购点 =(平均每日使用量 × 交货时间)+ 安全库存
  • DAX RANKX 函数在数据变化时自动支持 ABC 分类
  • Power BI 中的需求预测通过 DAX 或 Azure ML 集成使用线性回归
  • 缓慢移动和过时 (SLOB) 库存识别可节省大量持有成本
  • Power BI 连接到 ERP 库存表(Odoo、SAP、NetSuite),无需数据移动

库存分析数据模型

核心库存表

Inventory_Snapshot(每天/每周每件商品一行 — 时间点库存水平):

专栏描述
代码0库存盘点日期
代码0FK 到项目/产品尺寸
代码0FK 至仓库/地点
代码0现货库存数量
代码0未结订单数量
代码0承诺未平仓订单数量
代码0QoH - 保留
代码0平均或标准成本
代码0现有数量 × 单位成本

Inventory_Movements(每笔股票交易一行):

专栏描述
代码0交易ID
代码0FK 转项目
代码0FK 至地点
代码0搬家日期
代码0收货、出售、转让、调整、退货
代码0移动数量(正=入,负=出)
代码0移动时的单位成本

Sales_Lines(每个销售订单行一行用于需求分析):

  • 代码0代码1代码2代码3代码4代码5代码6代码7

Purchase_Orders(用于交货时间和采购分析):

  • 代码0代码1代码2代码3代码4代码5代码6

Dim_Item(产品尺寸):

  • code0code1code2code3code4code5code6code7code8code9code10code11

使用 DAX 的核心库存 KPI

库存水平衡量

// Current Stock on Hand (point-in-time)
Stock on Hand =
CALCULATE(
    SUM(Inventory_Snapshot[QuantityOnHand]),
    Inventory_Snapshot[SnapshotDate] = MAX(Inventory_Snapshot[SnapshotDate])
)

// Stock Value (current)
Stock Value =
CALCULATE(
    SUM(Inventory_Snapshot[StockValue]),
    Inventory_Snapshot[SnapshotDate] = MAX(Inventory_Snapshot[SnapshotDate])
)

// Available to Promise (ATP)
Available to Promise =
CALCULATE(
    SUM(Inventory_Snapshot[QuantityAvailable]),
    Inventory_Snapshot[SnapshotDate] = MAX(Inventory_Snapshot[SnapshotDate])
)

// Stock on Order (incoming POs)
Stock on Order =
CALCULATE(
    SUM(Inventory_Snapshot[QuantityOnOrder]),
    Inventory_Snapshot[SnapshotDate] = MAX(Inventory_Snapshot[SnapshotDate])
)

// Projected Stock (current + on order - reserved)
Projected Stock = [Stock on Hand] + [Stock on Order] - [Stock Reserved]

库存周转率

// COGS in Period (for turnover denominator)
Total COGS =
SUMX(
    FILTER(Inventory_Movements, Inventory_Movements[MovementType] = "Sale"),
    Inventory_Movements[Quantity] * Inventory_Movements[UnitCost]
)

// Average Inventory Value (beginning + ending / 2)
Avg Inventory Value =
AVERAGEX(
    VALUES(Date[Month]),
    CALCULATE(
        SUM(Inventory_Snapshot[StockValue]),
        Inventory_Snapshot[SnapshotDate] = MAX(Inventory_Snapshot[SnapshotDate])
    )
)

// Inventory Turnover Ratio
Inventory Turnover =
DIVIDE([Total COGS], [Avg Inventory Value], 0)

// Days Inventory Outstanding (DIO)
Days Inventory Outstanding =
DIVIDE(365, [Inventory Turnover], 0)

// Benchmark comparison (industry varies widely)
// Manufacturing: 6-12x | Retail: 4-6x | Electronics: 8-15x
Turnover vs Benchmark =
[Inventory Turnover] -
LOOKUPVALUE(
    Industry_Benchmark[InventoryTurnover],
    Industry_Benchmark[Category],
    SELECTEDVALUE(Dim_Item[Category])
)

ABC 分析

ABC 分析根据库存项目的收入或成本贡献对它们进行分类:

  • A 项目:收入/销货成本的前 80% — 高优先级,严格控制
  • B 项目:接下来 15% — 适度控制
  • C 项目:底部 5% — 最小程度的监督
// Revenue contribution per item (last 12 months)
Item Revenue 12M =
CALCULATE(
    SUM(Sales_Lines[Revenue]),
    DATESINPERIOD(Date[Date], TODAY(), -12, MONTH)
)

// Cumulative revenue % (for ABC cutoff)
Cumulative Revenue % =
DIVIDE(
    SUMX(
        FILTER(
            ALL(Dim_Item),
            RANKX(ALL(Dim_Item), [Item Revenue 12M], , DESC) <=
            RANKX(ALL(Dim_Item), [Item Revenue 12M], , DESC)
        ),
        [Item Revenue 12M]
    ),
    CALCULATE([Item Revenue 12M], ALL(Dim_Item)),
    0
)

// ABC Classification (calculated column in Dim_Item, refreshed periodically)
ABC Class =
VAR CumPct = [Cumulative Revenue %]
RETURN
SWITCH(TRUE(),
    CumPct <= 0.80, "A",
    CumPct <= 0.95, "B",
    "C"
)

// ABC Summary measure
A Items Count = CALCULATE(COUNTROWS(Dim_Item), Dim_Item[ABC Class] = "A")
A Items Revenue % = DIVIDE(
    CALCULATE([Item Revenue 12M], Dim_Item[ABC Class] = "A"),
    CALCULATE([Item Revenue 12M], ALL(Dim_Item)),
    0
)

ABC-XYZ 矩阵

使用 XYZ 分类扩展 ABC 以应对需求变化:

  • X:需求波动性低(CV < 0.5)——可预测,规划效率
  • Y:中等变异性 (CV 0.5-1.0) — 一些不确定性
  • Z:高可变性 (CV > 1.0) — 不可预测,针对服务水平进行规划
// Coefficient of Variation for demand variability
Demand CV =
DIVIDE(
    STDEV.P(Sales_Lines[Quantity]),
    AVERAGE(Sales_Lines[Quantity]),
    0
)

// XYZ Classification
XYZ Class =
SWITCH(TRUE(),
    [Demand CV] < 0.5, "X",
    [Demand CV] < 1.0, "Y",
    "Z"
)

AX 细分市场(高收入、可预测的需求)接受最严格的再订购管理。 CZ 细分市场(收入低、不可预测)可能会被淘汰或按订单生产。


再订购点和安全库存计算

再订购点公式

再订购点 =(平均每日使用量 × 提前期)+ 安全库存

// Average Daily Usage (last 90 days)
Avg Daily Usage =
DIVIDE(
    CALCULATE(
        SUM(Sales_Lines[Quantity]),
        DATESINPERIOD(Date[Date], TODAY(), -90, DAY)
    ),
    90,
    0
)

// Reorder Point calculation
Calculated Reorder Point =
ROUND(
    [Avg Daily Usage] * AVERAGE(Dim_Item[LeadTimeDays]) +
    Dim_Item[SafetyStock],
    0
)

// Below Reorder Point flag
Below Reorder Point =
IF([Stock on Hand] < [Calculated Reorder Point], "Reorder Required", "OK")

// Days of Supply remaining
Days of Supply =
DIVIDE([Stock on Hand], [Avg Daily Usage], 0)

// Stockout Risk Score (0-100)
Stockout Risk =
SWITCH(TRUE(),
    [Days of Supply] < 7, 100,     -- Critical
    [Days of Supply] < 14, 75,     -- High risk
    [Days of Supply] < 30, 50,     -- Medium risk
    [Days of Supply] < 60, 25,     -- Low risk
    0                               -- OK
)

安全库存计算

// Safety Stock using statistical method
// SS = Z-score × σ(demand) × √Lead Time
Safety Stock Calculated =
VAR ZScore = 1.645   -- 95% service level
VAR DemandStdDev = STDEV.P(Sales_Lines[Quantity])  -- per day
VAR LeadTime = AVERAGE(Dim_Item[LeadTimeDays])
RETURN ROUND(ZScore * DemandStdDev * SQRT(LeadTime), 0)

滞销和过时 (SLOB) 库存

确定 SLOB 库存对于优化营运资本至关重要:

// Days Since Last Sale
Days Since Last Sale =
DATEDIFF(
    CALCULATE(
        MAX(Sales_Lines[OrderDate]),
        ALL(Date)
    ),
    TODAY(),
    DAY
)

// SLOB Classification
SLOB Class =
SWITCH(TRUE(),
    [Days Since Last Sale] > 365, "Obsolete",
    [Days Since Last Sale] > 180, "Slow Moving",
    [Days Since Last Sale] > 90, "At Risk",
    "Active"
)

// SLOB Inventory Value
SLOB Value =
CALCULATE(
    [Stock Value],
    Dim_Item[SLOB Class] IN {"Slow Moving", "Obsolete"}
)

// SLOB as % of total inventory
SLOB % =
DIVIDE([SLOB Value], [Stock Value], 0)

需求预测可视化

Power BI 可以使用以下方式可视化需求预测:

内置预测(分析窗格)

右键单击折线图 → 分析窗格 → 预测:

  • 预测长度:12个月
  • 置信区间:95%
  • 季节性:自动检测

这使用指数平滑 (ETS) 算法 - 适用于简单、固定的需求模式。

自定义 DAX 线性预测

// Simple Linear Regression Forecast
Demand Forecast =
VAR LastPeriod = MAX(Date[MonthNum])
VAR ForecastPeriod = LastPeriod + 1  -- Next month
VAR N = COUNTROWS(VALUES(Date[Month]))
VAR SumX = SUMX(VALUES(Date[MonthNum]), Date[MonthNum])
VAR SumY = SUMX(VALUES(Date[Month]), [Monthly Sales Qty])
VAR SumXY = SUMX(VALUES(Date[Month]), Date[MonthNum] * [Monthly Sales Qty])
VAR SumX2 = SUMX(VALUES(Date[MonthNum]), Date[MonthNum]^2)
VAR Slope = DIVIDE(N*SumXY - SumX*SumY, N*SumX2 - SumX^2, 0)
VAR Intercept = DIVIDE(SumY - Slope*SumX, N, 0)
RETURN Intercept + Slope * ForecastPeriod

Azure ML 需求预测

对于复杂的需求预测,请集成 Azure 机器学习:

  1. 根据 Azure ML 中的历史需求数据训练 Prophet 或 ARIMA 模型
  2. 部署为 Azure ML Web 服务
  3. 使用 AI Insights 集成从 Power BI 数据流进行调用
  4. 将预测值显示为项目维度中的一列

库存仪表板架构

第 1 页:执行清单摘要

  • 总股票价值(带环比变化的 KPI 卡)
  • 库存周转率(标准与行业基准)
  • 库存周转天数(带趋势的 KPI)
  • 缺货商品计数(警报卡,如果 >0 则为红色)
  • SLOB 值(KPI 占总数的百分比)
  • 按类别划分的股票价值(树形图)
  • 再订购警报(表:商品、QoH、再订购点、供应天数)

第 2 页:ABC 分析

  • 帕累托图(按收入排名的项目,累计百分比)
  • ABC 分布(圆环图:按类别划分的计数和值)
  • ABC-XYZ 矩阵(散点图:X 上的收入,Y 上的 CV,气泡大小 = 股票价值)
  • 顶级 A 项目表(项目、收入、营业额、库存价值、利润)

第 3 页:库存监控

  • 库存水平热图(位置×类别)
  • 以下再订购点商品(带有缺货风险颜色的表格)
  • 收到采购订单时间线(甘特图或条形图)
  • 库存年龄分析(条形图:0-30、30-60、60-90、90+天)

第 4 页:需求和预测

  • 实际需求与预测(带预测阴影的折线图)
  • 按类别划分的需求变化(箱线图或带有误差线的条形图)
  • 季节性需求模式(热图:月份×星期几)
  • 排名前 20 的快速移动者(按每周销售量排列的条形图)

常见问题

将 Power BI 连接到 ERP 以获取库存数据的最佳方式是什么?

连接方法取决于您的 ERP。对于 Odoo,直接连接到只读副本上的 PostgreSQL。对于 SAP,将 SAP HANA 连接器与清单 CDS 视图结合使用。对于 NetSuite,请使用 SuiteAnalytics Connect ODBC。对于 Dynamics 365 Business Central,请使用 Business Central 连接器。对于所有 ERP 连接,请使用对库存表具有只读访问权限的专用分析用户帐户,并安排非高峰时间刷新以最大限度地减少 ERP 负载。

如何在 Power BI 中处理多仓库库存?

将位置维度添加到数据模型中,其中包含仓库名称、城市、国家/地区和类型(配送中心、零售店等)等属性。所有库存快照行都包含 LocationID。构建跨所有位置聚合或通过切片器按选定位置进行过滤的度量。对于仓库间转移分析,MovementType =“Transfer”的 Inventory_Movements 表会跟踪地点之间的库存移动。

什么是好的库存周转率?

这在很大程度上取决于行业。电子产品:8-15x(高速度,低利润)。杂货/快速消费品:15-30x。汽车零件:3-6x。时装零售:4-8x(季节性)。工业制造:3-8x。将您的营业额与行业基准而不是通用目标进行比较。 “理想”比率平衡服务水平(避免缺货)和持有成本(避免过剩)。

Power BI 可以预测我何时会缺货吗?

是的——“供应天数”指标计算当前库存按平均每日销售率计算的天数。当这低于交货时间 + 安全库存缓冲区时,Power BI 可以将该项目标记为有风险,并将其显示在重新订购警报表中。对于预测性库存,集成 Azure ML 需求预测来预测未来销售,并根据预测而非历史需求计算缺货风险何时变得严重。

如何在 Power BI 中可视化库存老化?

使用堆积条形图显示每个年龄段(0-30 天、31-60、61-90、91-180、180+ 天)的股票价值百分比。账龄是从最旧批次的接收日期开始计算的。随着时间的推移跟踪这一趋势,看看您的老化情况是在改善(转向更新鲜的库存)还是恶化(积累旧库存)。以红色突出显示 90 天以上的股票作为 SLOB 风险指标。


后续步骤

Power BI 中的有效库存分析可降低持有成本、防止缺货并改善现金流——这三个指标对供应链和运营领导力最重要。正确建立数据模型(基于快照的库存水平、基于移动的流量分析)是其他一切的基础。

ECOSIRE 的 Power BI 团队构建连接到您的 ERP 系统(Odoo、SAP、NetSuite、Dynamics 365 等)的供应链和库存仪表板。我们将 ABC 分析、再订购警报系统和需求预测可视化作为生产就绪的仪表板来实施。

探索我们用于供应链分析实施的Power BI 仪表板开发服务,或联系我们的团队 讨论您的库存数据源和分析要求。

E

作者

ECOSIRE Research and Development Team

在 ECOSIRE 构建企业级数字产品。分享关于 Odoo 集成、电商自动化和 AI 驱动商业解决方案的洞见。

通过 WhatsApp 聊天