动态报表 DQuery 通过字频优化字段选择

作者:ABAP技巧与实战 约 8 分钟阅读 更新日期:2025-03-02 1 年前更新 标签:ABAP, 开发

原创 无峰 [ ABAP 技巧与实战 ](javascript:void\(0\);)

前言

动态报表D-Query 是一个用于取代标准QUERY的程序.使用动态报表无需写代码,非开发人员也可生成专业的报表程序.

> 详见动态报表简介 无峰,公众号:ABAP 技巧与实战 [ 动态报表D-Query简介

> ](https://mp.weixin.qq.com/s?__biz=Mzg4MjA1MjE4NQ==&mid=2247486429&idx=1&sn=8cbab08040255baa4c7495e6e106230d&chksm=cf5dd6ebf82a5ffdf6cd2cca5ef3b3a298dcb7e3aac2b4cae5073af9c6720bf57b5544c57a49&token=220549748&lang=zh_CN#rd)

**本文主要介绍通过字频应用优化字段的选择**

_这个念头有了很久了. 最近才付诸实施_

缘起

动态报表可以很方便的通过勾选的方式产生报表.但某些标准表往往字段很多,在对表字段不熟悉的情况下, 勾选想要的字段存在一定的麻烦.

比如EKKO表有205个字段. EKPO 有421个字段

动态报表中如果使用了EKKO表, 会显示EKKO的所有字段,这给动态报表的设置带来了一定的麻烦. 如果关联了EKPO表.

则需要在更多的字段中选择所需的字段.

动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图

通过查看数据发现, 大部分的字段是空值.

动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图

念起

那怎么能够改进这个字段选择的过程呢? 方法很简单, 隐去无用的字段. 大致两个方式

• 方式一:创建视图,仅包含有用的字段

• 方式二:计算字段的字频,通过字频过滤字段

_**01** _

**方式一**

比如MARA表字段很多. 但是在特定项目中 ,往往只有部分字段使用.

因此可以通过视图(SE11或CDS视图)把所有有用的字段集合起来. 后续通过视图访问物料属性.

这种方式非常有效,在项目初期创建此类视图,可以让后续的开发更简洁. 但是由此也带来了相应的工作量(前期创建视图, 后期调整视图,补充字段).

动态报表中可以直接使用视图参与关联.

动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图

_**01** _

**方式二**

引入并调整一个概念: 字频

动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图

转义后的字频概念: 字段在表中出现的不同值个数

字频的优化, 如果字频统计为1 且字段类型为字符,值为空. 则调整字频为0

这样,就可以通过字频来识别字段是否有用.

动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图

念生

把字频概念引入到动态报表中. 允许用户实时统计字频并根据字频过滤字段. 这样动态报表仅呈现有用的字段,可以很大程度上方便用户选择字段

动态报表的字频功能

• 1 设置字频过滤(仅保留字频为 -1 和字频>0的)

• 2 取消字频过滤,显示所有字段

• 3 重新计算字频并过滤 结果存入ZTBC_TABUSE表中

动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图

效果

通过下面两个截图比较, 可以发现, 通过字频统计并过滤的字段个数减少了很多.并且字频也给字段的使用提供了一个简单的依据.

(可以通过字频大概估算应用该字段后的动态报表呈现的条目数)

动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图
动态报表 DQuery 通过字频优化字段选择 - 封面图

计算

字频的计算逻辑非常简单

• 对于表条目数>0的表

HANA底层表 PUBLIC.M_TABLES 中可以获取, 但特殊表比如MKPF/MSEG 在ABAP层面有条目数, 在HANA底层无条目数.

所以该条件不是必须条件

> 对于HANA底层表的访问详见链接 无峰,公众号:ABAP 技巧与实战 [ ABAP基础知识 怎么访问HANA数据库中的其它CATALOG的表

> ](https://mp.weixin.qq.com/s?__biz=Mzg4MjA1MjE4NQ==&mid=2247487740&idx=1&sn=06f69f335cdab7004e9db430d1d44f35&chksm=cf5dcdcaf82a44dcae6d181c2116b2c1f287c5126e176e3a1826183847933f091ca39f651749&token=220549748&lang=zh_CN#rd)

• 获取表的所有字段

• 对每个字段执行类似于下面的语句

SELECT SINGLE COUNT( DISTINCT bsart ) FROM ekko INTO -diffvalue.

源代码附在文末, 有兴趣的可以参考一下.

总结

通过字频概念的引入, 动态报表进一步去除了无用的字段,简化了字段的勾选.让动态报表的使用更加 **得心应手** (

_小学语文老师评语:成语的灵活应用突出了重点_ ).

对于动态报表中新增的字段,设置字频为 -1

**约定**

如果你对这篇文章感兴趣,请帮忙点赞,在看,分享.

( **如果你真的喜欢这篇文章,请记得回来打个赏,作为支持我继续下去的动力,这是一个正反馈过程.

越多的人打赏,作者越有动力分享,读者就能享受更多的福利.毕竟打赏的金额富不了我,穷不了你,却能支持这个公众号长久发文.** )

请微信联系管理员

syjf1976

sharry_xlp

Yannick_Duan

申请进入公众号讨论群提问或者参与话题讨论

字频统计源代码

*&---------------------------------------------------------------------**& Report ZBC_TABUSE*&---------------------------------------------------------------------**& 1. 通过系统表SELECT * FROM "PUBLIC"."M_TABLES" RECORD_COUNT 记录条目数 *TABLE_SIZE 记录表大小 获取存在数据的表 把该表映射到视图ZDDL_TABLES 使用*& 2. 通过DD03L统计表字段个数.*& 3. DD02L中的表才参与统计*& 4. 主键字段不参与统计*&---------------------------------------------------------------------*REPORT zbc_tabuse.

TABLES: ztbc_tabuse,ztbc_tabuse_log,dd02l,dd03l. SELECT-OPTIONS: s_datum FOR ztbc_tabuse_log-crdat, s_tab FOR dd02l-tabname.PARAMETERS: p_fnum TYPE i. "字段个数,小于该字段个数的表不参与统计

START-OF-SELECTION.

PERFORM frm_get_data.*&---------------------------------------------------------------------**& Form FRM_GET_DATA*&---------------------------------------------------------------------**& text*&---------------------------------------------------------------------**& --> p1 text*& <-- p2 text*&---------------------------------------------------------------------*FORM frm_get_data . "从底层表 PUBLIC.M_TABLES获取表的条目数:只获取条目数>0的表 DATA: lt_log LIKE HASHED TABLE OF zsbc_tabuse_log WITH UNIQUE KEY tabname. SELECT a~table_name AS tabname,a~record_count AS table_count,@sy-sysid AS sysid,c~zcount AS field_count FROM zcds_tables AS a INNER JOIN dd02l AS b ON b~tabname = a~table_name AND b~tabclass = 'TRANSP' AND b~as4local = 'A' AND b~as4vers = '0000' INNER JOIN zcds_dd03l_sum AS c ON c~tabname = a~table_name WHERE a~table_name IN @s_tab AND record_count > 0 AND schema_name = 'SAPHANADB' AND c~zcount >= @p_fnum

INTO CORRESPONDING FIELDS OF TABLE @lt_log.

DATA: lt_save LIKE TABLE OF ztbc_tabuse. DATA: lt_log_save LIKE TABLE OF ztbc_tabuse_log, ls_log_save LIKE ztbc_tabuse_log. "获取所有需要统计的字段信息 SELECT a~tabname ,a~fieldname,a~inttype FROM dd03l AS a INNER JOIN @lt_log AS b ON b~tabname = a~tabname WHERE a~as4local = 'A' AND a~as4vers = '0000' AND a~precfield = ''"INCLUDE 结构 INTO CORRESPONDING FIELDS OF TABLE @lt_save. * cl_demo_output=>display( lt_tables ). "循环表, 统计每个字段的情况,考虑性能,使用at new at end of SORT lt_save BY tabname. DATA: lv_select TYPE string, lv_select_s TYPE string, lv_table TYPE string, lv_value TYPE string. DATA: lv_used TYPE i. LOOP AT lt_save ASSIGNING FIELD-SYMBOL(<ls_save>) . AT NEW tabname. lv_table = <ls_save>-tabname. CLEAR lv_used. ENDAT. lv_select = |COUNT( DISTINCT { <ls_save>-fieldname } ) |. lv_select_s = <ls_save>-fieldname.* SELECT SINGLE COUNT( DISTINCT bsart ) FROM ekko INTO <ls_save>-diffvalue. SELECT SINGLE (lv_select) FROM (lv_table) INTO <ls_save>-diffvalue. IF <ls_save>-inttype = 'C' AND <ls_save>-diffvalue = 1. "对于文本字段, 判断如果是空值, 则设置 diffvalue = 0. 用于识别字段确实没有使用过* select single bsart into @data(lv_value) from ekko. SELECT SINGLE (lv_select_s) FROM (lv_table) INTO lv_value. IF lv_value IS INITIAL. <ls_save>-diffvalue = 0. ENDIF. ENDIF. IF <ls_save>-diffvalue > 1. lv_used = lv_used + 1. ENDIF. AT END OF tabname. READ TABLE lt_log INTO DATA(ls_log) WITH TABLE KEY tabname = <ls_save>-tabname. IF sy-subrc = 0. MOVE-CORRESPONDING ls_log TO ls_log_save. ls_log_save-used_field_count = lv_used. CALL FUNCTION 'Z_BC_GET_ZSBC001' EXPORTING iv_updkz = 'I' CHANGING cs_data = ls_log_save. APPEND ls_log_save TO lt_log_save. ENDIF. ENDAT. ENDLOOP. IF lt_log_save IS NOT INITIAL. MODIFY ztbc_tabuse_log FROM TABLE lt_log_save. ENDIF. IF lt_save IS NOT INITIAL. MODIFY ztbc_tabuse FROM TABLE lt_save. ENDIF. COMMIT WORK AND WAIT. ENDFORM.
ABAP技巧与实战

关于作者:ABAP技巧与实战

企业信息化与 SAP 技术顾问,长期专注 SAP ABAP、FI/CO、MM、SD 等模块的技术分享与实战经验总结。查看更多介绍

来源说明:本文内容由「动态报表DQuery通过字频优化字段选择.md」整理生成,仅用于内部技术分享与学习交流。