SAP 物料账未分摊差异分析

今天在开发处理未分摊差异程序的时候,偶然在网络上看到一篇这样的文章,挺有意思的,特意转载过来,方便大伙学习之用,若有异议,立即撤回。

利用CKMLCP运行完物料分类账之后,差异科目余额通常为0,如果不为0则说明有未分摊差异。一般情况下,CKMLCP执行到“过账清算”前,需要执行CKMVFM检查差异分摊情况,分析未分摊差异原因。

哪些情况下会形成未分摊差异呢?

1)库存数量不足,不能完全吸收差异

例如,

A)采购发票跨月结算,发票数量大于库存数量;

B)生产订单跨月结算,订单数量大于库存数量。

SAP允许将这部分差异全部由库存吸收,在CKMLCP运行物料分类账“单级处理确定”时勾选“不经库存覆盖检查”即可。

 

2)物料库存为0。

发票校验(订单结算)形成差异,此差异不能被分摊。

3)负差太大,将库存冲为负数,此时差异不分摊

如下图,库存成本为10,312.61 + 6,312,813.53,当期生成差异为-114,314,314.40,直接将库存冲为负数,此时SAP无法处理,形成未分摊差异。

 

 

4)订单有投入,但无产出,差异不能上卷,形成未分配差异

例如,

A)没有启用WIP重估功能,S价的物料投入订单,但订单没有产出;

B)生产订单当期没产出,但有投料,月底设置状态为TECO(这种为不正常的情况,需要从业务操作上进行规范,及时投料,及时关闭订单)。

 

5)整除不尽形成的未分配差异,这种差异一般比较小

例如1.00分给3个人,每人分的0.33元,但是有0.01是无法分配的。

总结

作为成本核算人员,分析未分摊差异是必备技能之一。根据差异分摊的三个原则“差异随库存走;差异层层上卷;谁消耗,谁承担”,库存不足时可能形成差异,差异上卷没有依据时可能形成差异,以及差异太大将库存金额冲为负数时形成差异。

 

 

<think>我们正在处理ABAP SQL查询错误:当使用内联声明(inline declarations)或带有泛型引用的NEW操作符时,投影列表中的所有表达式都必须有别名。 在ABAP中,内联声明(DATA(...))和NEW #(用于创建匿名数据对象)在Open SQL中使用时,要求SELECT列表中的每个字段或表达式都必须有一个别名。 错误原因: 在ABAP的Open SQL中,如果使用内联声明(如SELECT ... INTO TABLE @DATA(itab))或使用NEW操作符(如SELECT NEW #( ... ) ...),那么SELECT子句中的每一个表达式都必须通过AS alias指定别名。 为什么需要别名? 1. 内联声明:编译器需要根据别名来确定内联表或结构的组件名称。 2. 泛型引用(NEW #):由于是匿名创建,编译器需要别名来构造结果的结构。 解决方案: 为SELECT列表中的每一个表达式(包括直接字段、计算字段、聚合函数等)都添加AS alias。 示例: 假设我们有一个表SFLIGHT,我们想要选择CARRID, CONNID, 以及一个计算字段(PRICE * 1.1)。错误写法如下: SELECT carrid, connid, price * 1.1 FROM sflight INTO TABLE @DATA(itab). " 这里会报错,因为计算字段没有别名 正确写法是为计算字段添加别名: SELECT carrid, connid, price * 1.1 AS calc_price FROM sflight INTO TABLE @DATA(itab). 同样,如果使用NEW操作符: SELECT NEW #( carrid, connid, price * 1.1 ) " 这里会报错,因为第三个表达式没有别名 FROM sflight INTO TABLE @DATA(itab). 正确写法是: SELECT NEW #( carrid AS carr_id, connid AS conn_id, price * 1.1 AS calc_price ) FROM sflight INTO TABLE @DATA(itab). 注意:在NEW #(...)中,每个字段都必须有别名,即使原本的字段名(如carrid)也需要通过AS指定别名(因为NEW #创建的是匿名结构,需要显式指定组件名)。 另外,如果使用内联声明但不使用NEW,而是直接选择多个字段到结构或表,那么只有那些不是简单字段(比如计算字段)需要别名吗?实际上,在ABAP中,内联声明要求所有字段都必须有别名(包括直接字段),但实际测试中,对于直接字段(没有计算)可以不使用别名,但是为了统一和避免错误,建议所有字段都加上别名。然而,根据ABAP帮助文档,当使用内联声明时,所有表达式(包括直接字段)都必须有别名。因此,安全做法是全部加上别名。 例如: " 以下写法在内联声明中会报错,因为字段没有别名(尽管是直接字段) SELECT carrid, connid FROM sflight INTO TABLE @DATA(itab). " 错误!在内联声明中,即使直接字段也需要别名? 实际上,根据ABAP版本和上下文,对于直接字段,有时可以省略别名(但计算字段绝对不能省略)。但严格来说,根据错误消息的要求,只要使用了内联声明,所有表达式都必须有别名。因此,为了避免错误,建议在SELECT列表中的每个表达式都使用AS别名。 修正后: SELECT carrid AS carrid, connid AS connid FROM sflight INTO TABLE @DATA(itab). 或者,更简洁的写法(ABAP允许使用字段名本身作为别名,但注意,如果字段名很长,可以取一个简短的别名): SELECT carrid AS carrid, connid AS connid ... 但注意:在ABAP 7.40以后,对于直接字段,如果使用INTO TABLE @DATA(itab)且不指定别名,系统会自动使用字段名作为别名(即隐式别名)。但是,如果有一个计算字段,则必须显式指定别名,否则会报错。然而,当使用NEW操作符时,则必须显式指定所有字段的别名(包括直接字段)。 因此,为了确保代码的健壮性和可读性,建议在以下两种情况下为所有表达式显式指定别名: 1. 使用内联声明(INTO @DATA(...))并且SELECT列表中有计算字段或函数时。 2. 使用NEW操作符创建匿名结构时。 总结步骤: 1. 检查SELECT语句中是否使用了内联声明(如@DATA(...))或NEW操作符(如NEW #(...))。 2. 为SELECT列表中的每一个表达式(包括字段名、计算表达式、聚合函数等)添加AS alias子句。 3. 确保别名是有效的ABAP标识符(以字母开头,只能包含字母、数字和下划线)。 示例代码(使用内联声明和计算字段): SELECT carrid AS carrid, connid AS connid, price * 1.1 AS calc_price " 计算字段必须别名 FROM sflight INTO TABLE @DATA(itab). 示例代码(使用NEW操作符): SELECT NEW #( carrid AS carrid, connid AS connid, price * 1.1 AS calc_price ) FROM sflight INTO TABLE @DATA(itab). 注意:在NEW操作符中,别名将作为匿名结构的组件名,因此后续访问这些字段时需要使用别名(例如,在循环中,itab[1]-carrid)。 常见错误场景: - 忘记给计算字段(如price * 1.1)添加别名。 - 在使用NEW操作符时,忘记给直接字段添加别名(即使它是表字段)。 通过为所有表达式添加别名,可以避免这个编译错误。 引用说明: 根据ABAP编程指南,当使用内联声明或NEW操作符时,Open SQL要求投影列表中的每个表达式都必须有一个别名[^1]。 相关问题: 1. 在ABAP SQL中,内联声明(@DATA)还有哪些使用限制? 2. ABAP中NEW操作符创建匿名结构时,如何访问其字段? 3. 如何为ABAP SQL中的聚合函数(如SUM, AVG)指定别名?</think>### 解决 ABAP SQL 中因缺少别名导致的语法错误 在 ABAP SQL 查询中,当使用**内联声明**(`@DATA(...)`)或**泛型引用**(`NEW #(...)`)时,投影列表(`SELECT` 子句)中的所有表达式必须显式指定别名(`AS alias`)。否则会触发错误: > **"If inline declarations or NEW with generic reference are used, all expressions in the projection list must have an alias name."** #### 错误原因与解决方案 | **场景** | **错误示例** | **正确写法** | **核心原则** | |-------------------------|---------------------------------------------|---------------------------------------------|---------------------------------------| | **内联声明** (`@DATA`) | `SELECT carrid, connid, price INTO @DATA(lv_data)` | `SELECT carrid AS carrier, connid AS connection, price AS amount INTO @DATA(lv_data)` | 所有字段/表达式必须显式声明别名 | | **泛型引用** (`NEW #`) | `SELECT NEW #( carrid, connid ) FROM sflight` | `SELECT NEW #( carrid AS carrier, connid AS connection ) FROM sflight` | 匿名结构依赖别名定义字段名 | | **计算表达式** | `SELECT price * 1.1 INTO ...` | `SELECT price * 1.1 AS adjusted_price INTO ...` | 非直接字段的表达式必须别名化 | #### 分步解决指南 1. **识别问题位置** 检查 `SELECT` 子句中是否存在使用 `AS alias` 的表达式: - 直接字段(如 `carrid`) - 计算表达式(如 `price * 1.1`) - 函数调用(如 `CONCAT( firstname, lastname )`) 2. **添加显式别名** 为每个表达式添加 `AS alias_name`,别名需符合 ABAP 命名规范(字母开头,不含特殊字符): ```abap " 错误写法:缺少别名 SELECT carrid, connid, price * 1.1 FROM sflight INTO TABLE @DATA(lt_data). " ❌ 触发语法错误 " 正确写法:所有表达式有别名 SELECT carrid AS carrier_id, connid AS connection_id, price * 1.1 AS adjusted_price " ✅ 计算字段别名化 FROM sflight INTO TABLE @DATA(lt_data). ``` 3. **处理泛型引用 (`NEW #`)** 使用 `NEW #` 创建匿名结构时,每个字段必须通过别名定义结构组件名: ```abap " 错误写法:NEW # 中缺少别名 SELECT NEW #( carrid, connid ) FROM sflight INTO TABLE @DATA(lt_data). " ❌ 错误 " 正确写法:显式声明别名 SELECT NEW #( carrid AS carrier, connid AS connection ) FROM sflight INTO TABLE @DATA(lt_data). " ✅ ``` 4. **访问别名化字段** 结果集中的字段需通过别名访问: ```abap LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs>). WRITE: / <fs>-carrier_id, " 使用别名访问 <fs>-adjusted_price. ENDLOOP. ``` #### 关键注意事项 1. **聚合函数必须别名化** ```abap SELECT COUNT(*) AS total_count, AVG(price) AS avg_price ... " ✅ ``` 2. **即使字段名与目标相同仍需别名** ```abap " 即使字段名一致,NEW # 中仍需显式别名 SELECT NEW #( carrid AS carrid, connid AS connid ) ... " ✅ ``` 3. **内联声明与别名强绑定** 使用 `@DATA(...)` 时,编译器依赖别名推断数据结构。缺少别名将导致类型推断失败[^1]。 #### 示例:完整修复 ```abap " 错误代码(缺少别名) SELECT carrid, connid, price * 1.1, seatsmax - seatsocc AS available FROM sflight INTO TABLE @DATA(lt_flights). " ❌ 触发错误 " 修复后(所有表达式别名化) SELECT carrid AS airline_code, connid AS flight_number, price * 1.1 AS total_price, " 计算字段别名 seatsmax - seatsocc AS available_seats " 表达式别名 FROM sflight INTO TABLE @DATA(lt_flights). " ✅ 正确 ``` > **提示**:此约束是 ABAP Open SQL 的类型安全机制。编译器需通过别名确定结果集结构,尤其在泛型编程中[^1]。实践中,建议始终为投影列表中的表达式添加别名,避免隐式行为导致的错误。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值