Oracle SQL触发ORA-00904,如何实现各item近3次GRN最大价格统计
问题原因与调整方案
报错核心原因
ORA-00904是Oracle内联视图解析规则导致的:
- 写在
FROM子句中的内联视图(即你用来排序取GRN记录的子查询块),要求必须是完全独立可解析的SQL单元,禁止引用视图定义范围外的任何表别名 - 你原写法中将关联条件
gi.item_no = q.item_no放在了这个独立内联视图的内部,让需要独立解析的子查询去引用外层隔了两层的item_unit_quantity表别名q,Oracle解析时不会将外部列传递进内联视图,因此识别不到q.item_no - 这也解释了为什么你把关联条件改成固定常量时查询可以正常运行——此时内联视图完全独立,不需要引用外部列,自然不会报错,但所有结果行都会取同一个固定物料的价格,无法逐行匹配对应item_no。
正确实现写法
写法1:最小改动适配原逻辑(保留关联子查询结构)
将关联条件从内联视图内部移出,搭配分析函数实现编号逻辑,既避开内联视图的解析限制,也保证取数规则符合要求:
select q.item_no, sum(q.quantity) as total_quantity, ( select max(price) from ( -- 该子查询无外部列引用,可独立解析 select gi.item_no, gi.price, row_number() over(partition by gi.item_no order by g.grn_date desc) as rn from grn_item gi join grn g on gi.grn_no = g.grn_no ) sorted_grn -- 关联条件放在视图外层,与主查询的q表处于同一作用域 where sorted_grn.item_no = q.item_no and sorted_grn.rn <= 3 ) as PRICE from item_unit_quantity q where q.unit_no = 'PH00000096' group by q.item_no;
写法2:预聚合关联(性能更优,适合生产大数据量场景)
先通过CTE一次性计算出所有item_no对应的近3次GRN最大价格,再和主查询做关联,避免逐行触发的关联子查询带来的重复扫描开销:
with ranked_grn_price as ( select gi.item_no, gi.price, -- 按物料分组,按GRN日期倒序为每条记录编号 row_number() over(partition by gi.item_no order by g.grn_date desc) as rn from grn_item gi join grn g on gi.grn_no = g.grn_no ), item_target_price as ( -- 取每个物料编号<=3(即最新3次GRN)的价格最大值 select item_no, max(price) as price from ranked_grn_price where rn <= 3 group by item_no ) select q.item_no, sum(q.quantity) as total_quantity, p.price as PRICE from item_unit_quantity q left join item_target_price p on q.item_no = p.item_no where q.unit_no = 'PH00000096' group by q.item_no, p.price;
方案对比说明
- 写法1改动量小,和你最初的代码结构最接近,适合小数据量场景快速验证
- 写法2通过一次扫描完成所有GRN记录的排序聚合,后续直接关联预计算结果,执行效率远高于逐行关联的子查询写法,是生产环境推荐的实现方式
- 两种写法都严格遵循"每个item_no取最新3个GRN日期对应采购价格的最大值"的规则,不会出现之前关联失效的问题。
内容的提问来源于stack exchange,提问作者Claude
相关产品推荐
相关产品推荐

