库存 ABC 分类:好钢用在刀刃上

去年九月接手仓库,系统里在用的物料编码 6214 个,账面结存金额接近九千万。财务要求季度全盘,七个人进场,两天盘完一千二百个货位,剩下的一半靠估。第三个月我停了全盘,改成分类盘。

分类的办法不新鲜,就是 ABC:按出库金额从高到低排,累计占到七成的划 A,七成到九成的划 B,剩下的划 C。算完的结果是 A 类只有 342 个编码,却承担了七成出库金额;C 类 4885 个,加起来不到一成。

下面写三件事:这段分类怎么用一段 SQL 算出来、算完之后哪些动作要跟着改、以及为什么每个月都得重算一遍。中间踩的坑一并写上,省得别人再走一遍。

一、先把库存的真实分布看清楚

1.1 六千行明细里翻不出重点

接手第二周导出一份库存明细,6214 行,字段有编码、名称、规格、库位、结存数量、结存金额、近半年出库数量。按结存金额降序排,前两页全是单价高、半年没动过的设备备件。

这些件占着钱,但不流动。每天在动的螺丝、标签纸、包材,单价几毛,结存金额排在几百页之后。只看结存金额,会得出一个完全错误的重点。

库存的重点不在值多少钱,在一年周转几次。这句话听着像废话,可真按这个口径重排一次,很多人的判断会翻过来。

1.2 数量和金额对不上号

六千多个编码里,出库数量排在前一百的,贡献了八成出库行数;出库金额排在前一百的,贡献了六成金额。两张清单重叠的部分只有三十一个编码。

重叠少说明一件事:跑量大的件和占钱多的件是两拨东西。前者影响拣货效率和缺货投诉,后者影响资金占用和盘点风险。用一套办法管两拨东西,必然有一头管不住。

我们把两个口径都算了一遍,ABC 的排序依据定在出库金额上,数量的口径单独留一列做参考。理由是金额能跟财务对上,数量更适合拿去排拣货路径。

1.3 分类是分资源,不是贴标签

起初我在物料主数据里加了一个 ABC 字段,手工填。填了三天填四百多条,第四天发现新来的编码没人填,这个字段就废了。

分类的价值不在那个字母,在字母背后挂着的动作:多久盘一次、谁来盘、低于多少触发补货、放在哪个库位。字母是索引,动作才是内容。

后来把这个字段改成视图算出来的结果,每天夜间刷新,人不去维护它。人只维护动作规则,规则按字母分组配置。

二、一段 SQL 把分类算出来

2.1 口径先定死

口径上有三个选择要想清楚。时间窗取半年还是一年,我们取半年,因为季节性物料在一年窗口里会被摊平。金额取值用移动平均成本还是标准成本,我们跟财务保持一致,用标准成本。分母范围按整个仓库还是按库区,我们按库区,不同库区的物料结构差异太大。

这三件事不定死,每个月算出来的分类都会跳。分类一跳,盘点计划跟着乱,现场的人马上不信这张表。

定好之后写进视图,不再允许个人调整。

2.2 统计 SQL

用窗口函数做累计求和,按出库金额降序,看累计占比落在哪个区间。写法如下:

sql 复制代码
WITH usage AS (
  SELECT
    s.sku_code,
    s.warehouse_code,
    SUM(o.out_qty)               AS out_qty_180d,
    SUM(o.out_qty * s.std_cost)  AS out_amount_180d
  FROM stock_outbound o
  JOIN sku_master s ON s.sku_code = o.sku_code
  WHERE o.biz_date >= CURRENT_DATE - INTERVAL '180 days'
    AND o.status = 'CONFIRMED'
  GROUP BY s.sku_code, s.warehouse_code
),
ranked AS (
  SELECT
    u.sku_code,
    u.warehouse_code,
    u.out_qty_180d,
    u.out_amount_180d,
    SUM(u.out_amount_180d) OVER (
      PARTITION BY u.warehouse_code
      ORDER BY u.out_amount_180d DESC, u.sku_code
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS cum_amount,
    SUM(u.out_amount_180d) OVER (
      PARTITION BY u.warehouse_code
    ) AS total_amount
  FROM usage u
)
SELECT
  sku_code,
  warehouse_code,
  out_qty_180d,
  out_amount_180d,
  ROUND(cum_amount / NULLIF(total_amount, 0) * 100, 2) AS cum_pct,
  CASE
    WHEN cum_amount / NULLIF(total_amount, 0) <= 0.70 THEN 'A'
    WHEN cum_amount / NULLIF(total_amount, 0) <= 0.90 THEN 'B'
    ELSE 'C'
  END AS abc_class
FROM ranked
ORDER BY warehouse_code, out_amount_180d DESC;

两个细节。NULLIF 防分母为零,仓库里总有那么几个库区半年没有任何出库。累计求和用 ROWS BETWEEN 而不是 RANGE,金额相同的行会被 RANGE 并到一起,类别边界就漂了。

2.3 跑出来的分布

头一次跑出来,A 类 342 个编码,占 5.5%;B 类 987 个,占 15.9%;C 类 4885 个,占 78.6%。金额占比分别是 70.2%、20.1%、9.7%。

这组数字跟常说的二八分布接近,但尾部更重。翻了一下 C 类的明细,里面有大量一次性采购的工装夹具,买回来用一次就压在架上。

看清这一点,处置方向就有了:C 类不是不管,是先把死库存从 C 类里摘出去单独处理。

三、分类之后,动作要跟着改

3.1 盘点频率和责任分工

全盘改成循环盘点。A 类每周盘一次,仓库主管带一名仓管员,抽 80 个货位,两个半小时;B 类每月一次;C 类每季度抽百分之五的货位。

人没增加,盘点总量反而下来了。原来一次全盘两天半、七个人,现在每周固定两个半小时、两个人,全年工时少了四成,账实相符率从 91% 提到 98.6%。

责任也清楚了。A 类盘亏超过千分之三要写说明,C 类只在季度汇总里体现。不是 C 类不重要,是管理成本要跟风险匹配。

3.2 补货参数按类别分档

安全库存和补货点原来统一按一个月的用量设,A 类经常断,C 类堆成山。分档之后,A 类补货点定在 12 天用量、安全库存 5 天;B 类 20 天和 8 天;C 类改成按季度批量补,补货点 45 天。

参数一定要跟供应周期挂钩。A 类里有几个进口件,采购周期 60 天,补货点按 12 天设就是天天报警。后来在类别之上加了一层供应周期标签,同样是 A 类,周期长的单独放宽。

分档三个月后的数字:A 类缺货次数从每月 11 次降到 3 次,C 类库存金额压掉一成半。

3.3 库位和拣货路径

ABC 还影响货位布局。原来按物料大类分区,拣一张单要横穿整个库房。改成按出库频次分区,A 类集中到靠近出货口的三条巷道,拣货单平均行走距离从 210 米降到 96 米。

这件事的收益比盘点还直接。一个拣货员一天走十二公里,砍掉一半,等于多出半个人的产能。

但库位调整有成本,搬一次要停半个班。我们的做法是结合季度盘点做,盘空一条巷道就顺手重排,不单独安排搬仓。

拣货单的排序也跟着改了。原来按库位编码顺序排,现在按巷道走向加类别排,A 类的行排在单据前段。同样是二十行的单,走完的时间从四十分钟压到二十五分钟,中间少了三次回头找货。

四、分类会漂移,所以要定期重算

4.1 三个月后就不准了

上线三个月抽查,47 个编码的分类跟实际出库对不上。原因归成三类:新品导入,前面两个月没有出库记录,被归到 C;工艺变更,某个件突然放量;老产品停产,出库归零还挂在 A 类。

分类不准的后果不是报表难看,是动作错位。该周盘的 A 类去做了季度抽盘,该死库存清理的 C 类还在按周补货。

重算频率要跟变化速度匹配。我们定在每月一号自动重跑,跑完生成一张变化清单,只列出类别变了的编码,其他不看。

这张清单控制在三十行以内,大部分月份只有十来个编码换类。名单短,人才愿意逐条核对;一旦上百行,就没人看了,直接点确认。

4.2 新品和停产件单独走

新品有三个月观察期,观察期内不进 ABC,按试产件管:小批量、高频次、人工盯。三个月后出库数据够了再并进来。

停产件用另一套逻辑:连续六个月零出库、又没有未结订单的,打呆滞标记,从 ABC 视图里剔除,进呆滞品处置流程。处置有三条路:退供应商、内部转用、报废。

这两类不单独拎出来,ABC 的分布会被搅乱。新品刚上线出库为零,一定落在 C 类,然后被按 C 类的低频次管着,真放量的时候补货跟不上。

4.3 别让人随手改分类

系统刚上线有人提议,让计划员可以手工调某个件的类别。试了两周,A 类从 342 个涨到 519 个,理由都是这个件很重要。

重要是主观判断,ABC 是统计结果。两者混在一起,分类就没意义了。后来留了一个例外通道:确实要提升管理等级的,走变更单,写清理由和期限,三个月后自动回落。

这个通道一个月用五六次,都是金额不大但停线代价很高的件。有例外不可怕,例外变成常态才可怕。

常见问题

问:A 类占多少比例合适?

答:按金额切七成、两成、一成比较好用,落到编码数量上通常是百分之五到百分之十。A 类的编码数量超过一成,周盘的人力就撑不住,要么加人,要么承认盘点频次降下来。数量占比和金额占比要分开看,别拿一个数字套所有仓库。

问:出库金额用哪个价格算?

答:跟财务口径保持一致就行,标准成本或移动平均都可以,但不能这个月用这个、下个月用那个。价格口径一变,A 类的名单会整体挪位置,现场会以为系统出错。我们是在视图里固定取标准成本,财务年度调价时同步刷新。

问:半年窗口和一年窗口差多少?

答:在我们仓库,一年窗口会把季节性物料的峰值摊薄,导致几个只在旺季出货的件从 A 掉到 B。半年窗口的名单更贴当下的作业节奏,但对年度采购谈价的参考价值弱一些。两个都要的话,跑两套视图,别混用。

问:C 类是不是可以不管?

答:可以少管,不能不管。C 类的金额占比不到一成,编码数量却接近八成,占的库位面积往往超过一半。库位是稀缺资源,C 类里的呆滞件不清,A 类的扩容就没地方。我们的做法是每季度清一次呆滞,比盘点的优先级还高。

相关推荐
什么嘻嘻果冻1 天前
无代码开发平台的技术架构,恐象 AI 的生成引擎拆解
大数据·人工智能·低代码
驰骋工作流1 天前
低代码开发平台设计方向之一:基于菜单体系的开发平台设计驰骋BPM驰骋低代码低代码工作流引擎
低代码
risc1234562 天前
万变不离其宗
人工智能·低代码·云原生
Java小卷2 天前
Vue3 动态表单支持弹框组件
前端·vue.js·低代码
CORNERSTONE3652 天前
准备上MES,企业要先整理哪些基础数据?
低代码·erp·mes·企业数字化
骑着蜗牛撵大象3272 天前
ToolJet + PostgreSQL:后台表格、查询和流程,一次搭成可远程访问的业务系统
数据库·低代码·docker·postgresql·内部工具·tooljet
缓慢更新3 天前
表单引擎的存储建模:宽表与文档库的取舍
运维·服务器·网络·数据库·低代码·oracle·适配器模式
CORNERSTONE3653 天前
多品种、小批量生产,系统选型前要梳理哪些业务规则?
低代码·erp·企业数字化
什么嘻嘻果冻3 天前
无代码开发平台中的自然语言生成:恐象AI实现路径
大数据·人工智能·低代码