总览
SAP S4采用HANA数据库,本质上是用大内存、列存储实现快速的数据读取,其实存取效率应该还是下降了。 对于MM的库存管理,其实顾问们遇到最多的问题就是进销存/库龄/时点库存盘点之类的。 过去ECC面临海量数据时基本都推给BW了,现在HANA其实给了我们更多的可能。 SAP标准表变化
其实S4的版本中,库存表虽然看起来还跟ECC一致,其实底层已经完全不同了。 以MARD为例,如果你用HANA工具打开数据库链接,你会发现里面的数量字段,全都是0。 那系统时怎么做到SE16N看到库存数量呢?
第一步代理视图:
第二部DDL源视图:
大概套了了好几层,最后一层是 NSDM_DDL_MARD_AGG
第三步:SAP 标准的MARD数据视图
@AbapCatalog.preserveKey: true
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.sqlViewName: 'NSDM_V_MARD_AGG'
@EndUserText.label: 'MARD Compatibility View: Aggregation'
@DataAging.noAgingRestriction: 'false'
@ObjectModel.usageType.sizeCategory: 'L'
@ObjectModel.usageType.serviceQuality: #C
@ObjectModel.usageType.dataClass: #TRANSACTIONAL
@ClientHandling.algorithm: #AUTOMATED
@AccessControl.authorizationCheck: #NOT_ALLOWED
@AbapCatalog.viewEnhancementCategory: #PROJECTION_LIST
define view nsdm_e_mard_agg as
select from matdoc_extract
{
key mandt,
key matbf as matnr,
key werks,
key lgort_sid as lgort,
key lbbsa_sid as lbbsa,
key sobkz,
sum(stock_qty_l2) as stock_qty,
sum(stock_vkwrt_l2) as stock_vkwrt,
max(gjper_curr_per) as gjper_max,
sum(/cwm/stock_qty_l2) as /cwm/stock_qty
}
where stock_ind_l2 = ''
and (((sobkz = '' or sobkz = 'K')
and (lbbsa_sid = '01' or lbbsa_sid = '02' or lbbsa_sid = '07' or lbbsa_sid = '08'))
or (sobkz = ''
and (lbbsa_sid = '03' or lbbsa_sid = '04')))
group by mandt, matbf, werks, lgort_sid, lbbsa_sid, sobkz
可以看下SQL逻辑,就是简单的通过matdoc_extract表聚合而成。
而matdoc_extract是一张物料存储表,是MSEG的衍生表。默认行数应该与MATDOC一致。 月底应该有个默认作业,对matdoc_extract做同KEY同该期间的合并压缩。其实很多行业压缩率很低。
可见新版本HANA的SQL,已经可以做到过去通过ORCALE 直接 OPENSQL取数的效率。
那么问题来了,对我们有什么帮助呢? H表的变化
大家知道基本每个库存表都由有个H表,记录每个期末的库存。其实H表也这么调整了,而且解决了之前的一个难题。 过去如果一个物料/工厂/库位 在该期间没有货物移动,那么该期间的H表就是空。所以取月底的数逻辑十分复杂,效率低下,这个在新架构下基本没问题。 到天的时点库存
有些时候进销存/库龄可能不仅仅是按期间的,可能要到某一天。
其实我遇到这个需求是看看MARD的变化,本来想学MARD的方式也汇总那个表获取到天的库存,后来发现那个表只有期间没有天。其实SAP这么优化架构,大概率也会建立一些视图满足这个功能。找了下真有。
PMATSTOCKTIMESER
SE16N打开这个函数,执行时要输入参数,期间一般用D按天,然后开始/结束日期。
输出格式是按KEY的库存,基本支持各类特殊库存,按库存类型区分非限制、质检等信息。 简单处理下就是完整的库存数量了。效率OK 进一步的理解
我能不能自己汇总MSEG得到库存呢? 其实MSEG有很多问题,例如315只有一行,有一些无库存移动的行要排除。其实用MATDOC更好一些。完全可以实现,新SQL可以通过借贷 CASE WHEN THEN实现 SUM聚合与正负调整。 不过金额的处理还是不够完美。 例如MR21 调差 MIRO采购差异等这里还是缺的。K库存的金额其实不计入库存商品。有些特殊业务金额可能分布在不同的列等等。
这里我有个终极方案:自定义ZMSEG,将一些特殊处理全部放到物料凭证BADI->BEFORE_UPDATE方法里简单处理,同步写入ZMSEG。 简单处理了下业务类型的区分,金额/数量的取值/和正负。
通过作业或增强获取 ACODCA中 存货科目下非物料凭证生成的会计凭证,获取差异金额数据。同样处理好金额正负/取值等。 大概结果如下: 物料凭证数据
其它金额调整:下图应该是发票校验移动金额差。
那么就可以通过一个简单的SQL,获取某时点的库存数量/金额。
通过前面对业务类型的规划,可以实现对应对期间内数据的分列,实现一般进销存的的数据分列,SQL如下。
SELECT
* c~partner AS channel,
* c~name1,
a~werks AS werks,
a~satnr AS satnr,
goods_brand,
SUM(
CASE d~jxc_type
WHEN '1' THEN a~erfmg
END
) AS menge1,
SUM(
CASE d~jxc_type
WHEN '1' THEN a~dmbtr
END
) AS netwr1,
SUM(
CASE d~jxc_type
WHEN '2' THEN a~erfmg
END
) AS menge2,
SUM(
CASE d~jxc_type
WHEN '2' THEN a~dmbtr
END
) AS netwr2,
SUM(
CASE d~jxc_type
WHEN '3' THEN a~erfmg
END
) AS menge3,
SUM(
CASE d~jxc_type
WHEN '3' THEN a~dmbtr
END
) AS netwr3,
SUM(
CASE d~jxc_type
WHEN '4' THEN a~erfmg
END
) AS menge4,
SUM(
CASE d~jxc_type
WHEN '4' THEN a~dmbtr
END
) AS netwr4,
* SUM(
* CASE d~jxc_type
* WHEN '5' THEN a~erfmg
* END
* ) AS menge5,
*
* SUM(
* CASE d~jxc_type
* WHEN '5' THEN a~dmbtr
* END
* ) AS netwr5,
* SUM(
* CASE d~jxc_type
* WHEN '6' THEN a~erfmg
* END
* ) AS menge6,
*
* SUM(
* CASE d~jxc_type
* WHEN '6' THEN a~dmbtr
* END
* ) AS netwr6,
SUM(
CASE d~jxc_type
WHEN '7' THEN a~erfmg
END
) AS menge7,
SUM(
CASE d~jxc_type
WHEN '7' THEN a~dmbtr
END
) AS netwr7,
SUM(
CASE d~jxc_type
WHEN '8' THEN a~erfmg
END
) AS menge8,
SUM(
CASE d~jxc_type
WHEN '8' THEN a~dmbtr
END
) AS netwr8
* SUM(
* CASE d~jxc_type
* WHEN 'T' THEN a~erfmg
* END
* ) AS menget,
*
* SUM(
* CASE d~jxc_type
* WHEN 'T' THEN a~dmbtr
* END
* ) AS netwrt
INTO CORRESPONDING FIELDS OF TABLE @gt_alv
FROM zmseg AS a
LEFT JOIN zvmm_xpwl_info AS b ON a~satnr = b~matnr
* INNER JOIN zscmt0010 AS c ON a~werks = c~werks AND a~lgort = c~lgort
INNER JOIN zscm_jxc AS d ON a~bwart = d~bwart AND a~grund = d~grund AND a~shkzg = d~shkzg
WHERE a~budat_mkpf >= @p_date1
AND a~budat_mkpf <= @p_date2
AND a~werks IN @s_werks
* AND partner IN @s_partn
* AND budat_mkpf < @p_date1
* AND zxzdq IN @s_zxzdq
* AND zejqy IN @s_zejqy
* AND brand_id IN @s_brand
* AND zsyb IN @s_zsyb
AND a~satnr IN @s_satnr
AND saisj IN @s_saisj
AND saiso IN @s_saiso
AND goods_brand IN @s_brand1
AND mtart IN @s_mtart
GROUP BY
* c~partner,
* c~name1,
a~werks,
goods_brand,
a~satnr .
通过以上的方案,就可以实现把进销存或时点库存,甚至库龄的计算绝大部分都放到HANA的DB曾执行,ABAP应用层只做简单的数据拼装就可以,实现比较高的系统效率。
其实除了库存,还有信贷、甚至FI的科目余额、成本金额,都可以用此类方式实现(实际上你取标准表也是视图)。 所以HANA的方案实际上给业务顾问/ABAP顾问更强大的工具去做业务实现。