
*&---------------------------------------------------------------------*
*& Report YTEST_ZJ009
*&---------------------------------------------------------------------*
*&new为最新理解
*&---------------------------------------------------------------------*
REPORT YTEST_ZJ009.
*TABLES
TABLES:ytest_ng.
TYPES: BEGIN OF ty_data.
INCLUDE TYPE ytest_ng.
TYPES: flag TYPE char1,
END OF ty_data.
CONSTANTS:c_name2(4) VALUE '王明',
c_gender2(1) VALUE '男',
c_education2(2) VALUE '专科',
c_rank1(4) VALUE '销售主管',
c_rank2(4) VALUE '销售雇员',
c_name3(4) VALUE 'LISA',
c_gender3(1) VALUE '女',
c_education3(2) VALUE '本科',
c_name4(4) VALUE 'TOM'.
*&----------------------------------------------------------------------
* 练习一:内联声明
* 语法:DATA(...) ,ASSIGNING FILED-SYMBOL(…)
* ALPHA conversion
* Concatenation 串联
*&---------------------------------------------------------------------*
cl_demo_output=>write( '练习一:内联声明' ).
*1>取数ytest_ng表 第1 行数据到内表 并输出
SELECT *
FROM ytest_ng
INTO TABLE @DATA(gt_data)
UP TO 1 ROWS.
cl_demo_output=>write( gt_data ).
*3> 定义结构,读取内表第一行 并输出
READ TABLE gt_data INTO DATA(gs_data) INDEX 1.
IF sy-subrc EQ 0.
cl_demo_output=>write( gs_data ).
CLEAR gs_data.
ENDIF.
*4> 定义指针并修改000001人员职级为销售主管
CONSTANTS: c_xszg(10) VALUE '销售主管'.
LOOP AT gt_data ASSIGNING FIELD-SYMBOL(<fs_data>) .
<fs_data>-rank = c_xszg. "修改职级
ENDLOOP.
cl_demo_output=>write( gt_data ).
*4> 定义变量将000001工号去除前导0赋值给变量,并输出
DATA(lv_id) = |{ <fs_data>-id ALPHA = OUT }|.
cl_demo_output=>write( lv_id ).
*5> 定义变量输出去年的明天,并输出(使用新语法连接字符串)
DATA(lv_date) = |{ sy-datum(4) - 1 }{ sy-datum+4 + 1 } |.
*DATA(lv_date1) = ( sy-datum(4) - 1 ) && ( sy-datum+4 + 1 ).
cl_demo_output=>write( lv_date ).
*&----------------------------------------------------------------------
* 练习二:构造表达式
* 1. 值构造: VALUE - 创建一个类型为dypee的数据
* 2.1 构造结构
* 语法: ... VALUE dtype | #( [BASE dobj] comp1 = dobj1 comp2 = dobj2 ... ) ...
* 2.2 构造内表 :
* 语法: ... VALUE dtype | #( [BASE itab] ( (line1-com1 = dobj1) ( line2 ..) ... ) ...
* note: dytpe可接具体类型或者# ,接#数据类型必须确定
* 可以嵌套使用;
* 内表赋值不能带表头;
*&---------------------------------------------------------------------*
cl_demo_output=>write( '练习二:构造表达式' ).
*1> 结构赋值 (id :2 name :王明 gender:男 education:专科 rank:销售雇员)/输出
gs_data = VALUE #( id = 2 name = c_name2 gender = c_gender2
education = c_education2 rank = c_rank2 ).
DATA(gw_data) = VALUE ty_data( id = 2 name = c_name2 gender = c_gender2
education = c_education2 rank = c_rank2 ).
cl_demo_output=>write( gs_data ).
*2> 结构内附加王明薪资信息为6000/输出
gs_data = VALUE #( BASE gs_data salary = 6000 ).
cl_demo_output=>write( gs_data ).
*3> 结构内修改王明薪资为5000,更新至内表/输出内表
gs_data = VALUE #( BASE gs_data salary = 5000 ).
APPEND gs_data TO gt_data.
cl_demo_output=>write( gt_data ).
*4> 内表基础上附加额外数据之后,更新TABLE:YTEST_NG
*id :3 name :LISA gender:女 education:本科 rank:销售雇员
*id :4 name :TOM gender:男 education:专科 rank:销售雇员
gt_data = VALUE #( BASE gt_data ( id = 3 name = c_name3 gender =
c_gender3 education = c_education3 rank = c_rank2 salary = 4300 )
( id = 4 name = c_name4 gender =
c_gender2 education = c_education2 rank = c_rank2 salary = 4400 ) ).
cl_demo_output=>write( gt_data ).
*4.1new>内表基础上附加额外数据
APPEND VALUE #( id = 9 ) TO gt_data.
MODIFY ytest_ng FROM TABLE gt_data.
*5> 定义Range 表并赋值 id = 1 和 id>=3
DATA: r_range TYPE RANGE OF ytest_ng-id.
r_range = VALUE #( sign = 'I' ( option = 'EQ' low = 1 )
( option = 'GE' low = 3 )
sign = 'E' ( option = 'EQ' low = 2 )
).
cl_demo_output=>write( r_range ).
*&----------------------------------------------------------------------
* 练习三:内表操作
* 1. 内表表达式- 相当于READ TABLE
* 语法:… itab[ … ] …
* note: 如果未找到对应的记录就会抛出CX_SY_ITAB_LINE_NOT_FOUND异常,SY-SUBRC不会记录
* 可以通过line_exists预定义函数改进
* 2. 內表预定义函数
* 2.1 line_exists( ) - 判断记录是否存在
* 2.2 line_index( ) - 获取符合记录的索引值
* 3. 內表筛选-FILTER -筛选内表中的数据
* 语法: FILTER type( itab [EXCEPT] [IN ftab] [USING KEY keyname ]
* WHERE c1 op f1 [AND c2 op f2 [...] ] ) ...
* note: WHERE对应过滤的条件,是必须要指定的,注意有些操作符是不能在WHERE中使用的,如:OR , NOT 等
* EXCEPT如果不指定则表示满足条件的找出来,如果指定则表示不满足条件的找出来
* 4. 內表缩减
* 语法: ... REDUCE type(
* [let_exp]
* INIT {x1 = rhs1}|{<x1> = wrexpr1}|{x1|<x1> TYPE dtype1}
* {x2 = rhs2}|{<x2> = wrexpr2}|{x2|<x2> TYPE dtype2}
* ...
* FOR for_exp1
* FOR for_exp2
* ...
* NEXT ...
* {x1 = rhs1}|{<x1> = wrexpr1}
* {x2 = rhs2}|{<x2> = wrexpr2}
* ... ) ...
*&---------------------------------------------------------------------*
cl_demo_output=>write( '练习三:内表操作' ).
*1> 判断内表第3行是否存在,若存在,定义结构获取第3行记录/输出,定义变量获取第3行员工姓名/输出
IF line_exists( gt_data[ 3 ] ).
"获取第3行记录
TRY.
DATA(ls_data) = gt_data[ 3 ].
CATCH cx_sy_itab_line_not_found.
ENDTRY.
"获取第3行员工姓名
TRY.
DATA(lv_name) = gt_data[ 3 ]-name.
CATCH cx_sy_itab_line_not_found.
ENDTRY.
cl_demo_output=>write( ls_data ).
cl_demo_output=>write( lv_name ).
ENDIF.
*1.1new>读取内表
*data(ls_data3) = gt_data[ id = '10' ]. "若读不到会dump,一般处理方式为try catch
data(ls_data3) = VALUE #( gt_data[ id = 10 ] OPTIONAL ).
"加上VALUE…OPTIONAL,如果读不到的话,就是一个新定义的,所以为空
*1.2new>DEFAULT如果读不到就为默认值
data(wa_def) = VALUE ty_data( id = 10 name = 'rr').
CLEAR ls_data3.
ls_data3 = VALUE #( gt_data[ id = 10 ] DEFAULT wa_def ).
*2> 获取id=3,名字是1>中员工姓名的索引值,并输出其下一行人员信息
DATA(lv_index) = line_index( gt_data[ id = 1 name = '李华' ] ).
IF lv_index NE 0 .
CLEAR ls_data.
TRY.
ls_data = gt_data[ lv_index + 1 ].
CATCH cx_sy_itab_line_not_found.
ENDTRY.
cl_demo_output=>write( ls_data ).
ENDIF.
*3> 将gt_data用销售主管和销售雇员分别放到两个内表并输出(使用FILTER关键字语法)
"使用多个值筛选
DATA: gt_filter TYPE SORTED TABLE OF CHAR10
WITH NON-UNIQUE KEY table_line.
***INitialize filter Table
gt_filter = VALUE #( ( c_xszg ) )."可以写多个
"找出满足条件的数据
DATA(gt_out) = FILTER #( gt_data IN gt_filter WHERE rank = table_line ) .
cl_demo_output=>write( gt_out ).
"找出不满足条件的数据
DATA(gt_out_t) = FILTER #( gt_data EXCEPT IN gt_filter WHERE rank = table_line ) .
cl_demo_output=>write( gt_out_t ).
*new3.1>FILTER语法-使用SORT表
TYPES: BEGIN OF ty_001,
code TYPE char2,
value TYPE char10,
END OF ty_001.
DATA :itab TYPE SORTED TABLE OF ty_001 WITH NON-UNIQUE KEY code value.
DATA :itabs TYPE STANDARD TABLE OF ty_001 WITH NON-UNIQUE SORTED KEY cod COMPONENTS code value.
"初始化内表,此时被FILTER表应为SORT 或 HASH表
itab = VALUE #( ( code = '01' value = 'test01')
( code = '01' value = 'test001')
( code = '02' value = 'test02')
( code = '03' value = 'test003')
( code = '02' value = 'test021')
( code = '03' value = 'test031') ).
"直接Filter"找出满足条件的数据
DATA(it_filter) = FILTER #( itab WHERE code = '01' ).
"使用excpt 语句
DATA(it_exp) = FILTER #( itab EXCEPT WHERE code = '01' ).
*new3.2>FILTER语法
"标准表赋值
itabs = VALUE #( ( code = '01' value = 'test01')
( code = '01' value = 'test001')
( code = '02' value = 'test02')
( code = '03' value = 'test003')
( code = '02' value = 'test021')
( code = '03' value = 'test031') ).
"直接Filter"找出满足条件的数据
DATA(it_filters) = FILTER #( itabs USING KEY cod WHERE code = '01' ).
"显示数据
cl_demo_output=>new(
)->next_section( |初始化内表| )->write( itab
)->next_section( |直接Filter| )->write( it_filter
)->next_section( |使用excpt 语句| )->write( it_exp
)->next_section( |标准表赋值| )->write( itabs
)->next_section( |标准表Filter| )->write( it_filters
)->display( ).
*----------------------------------------------------------------------*
*4> a,内表行数
* b,内表中男性员工有几位
* c,累计内表gt_data中销售雇员工资之和
* d,定义结构将销售雇员工资总和、最大值、平均工资、员工个数输出
"内表行数
DATA(lv_lines) = lines( gt_data ).
"内表中男性员工有几位 -- 计数
DATA(lv_lines_nan) = REDUCE i( INIT x = 0
FOR ls_man IN gt_data WHERE ( gender = '男' )
NEXT x = x + 1 ).
cl_demo_output=>write( lv_lines ).
cl_demo_output=>write( lv_lines_nan ).
"累计内表gt_data中销售雇员工资之和 --简单汇总
TYPES: ty_sal TYPE p DECIMALS 2 .
DATA(lv_sum_salary) = REDUCE ty_sal( INIT sum_sal = VALUE ty_sal( )
FOR wa IN gt_data WHERE ( rank = c_rank2 )
NEXT sum_sal = sum_sal + wa-salary ).
cl_demo_output=>write( lv_sum_salary ).
TYPES:BEGIN OF ty_result,
sum TYPE p DECIMALS 2, "总和
max TYPE p DECIMALS 2, "最大值
min TYPE p DECIMALS 2, "最小值
avg TYPE p DECIMALS 2, "平均
cunt TYPE i, "记录数
END OF ty_result.
DATA(ls_result) = REDUCE ty_result( INIT res =
VALUE ty_result( min = 999999999 max = 0 ) "给一个最大值0,给一个最小值相对大的数据,然后再NEXT中比较大小
FOR <fs_data1> IN gt_data WHERE ( rank = c_rank2 )
NEXT res-sum = res-sum + <fs_data1>-salary "工资总和
res-max = nmax( val1 = res-max val2 = <fs_data1>-salary )"最高工资
res-min = nmin( val1 = res-min val2 = <fs_data1>-salary )"最di工资
res-cunt = res-cunt + 1 "几个销售雇员
).
ls_result-avg = ls_result-sum / ls_result-cunt. "平均工资
cl_demo_output=>write( ls_result ).
*4.1>复杂汇总 -- 按照group汇总与at new ,at end ,loop group by类似
TYPES: BEGIN OF ty_002,
code type char2,
group type char1,
quan type i,
end of ty_002.
DATA itab1 TYPE TABLE OF ty_002
WITH NON-UNIQUE SORTED KEY grp COMPONENTS group.
itab1 = VALUE #( ( code = '1' group = 'A' quan = 1 )
( code = '1' group = 'A' quan = 3 )
( code = '3' group = 'A' quan = 2 )
( code = '2' group = 'C' quan = 4 )
( code = '2' group = 'A' quan = 5 )
( code = '3' group = 'B' quan = 8 )
( code = '3' group = 'A' quan = 4 )
( code = '1' group = 'C' quan = 2 ) ).
"按照group汇总
DATA itabg TYPE TABLE OF ty_002.
LOOP AT itab1 INTO data(ls_itab1).
DATA(ls_check) = VALUE #( itabg[ group = ls_itab1-group ] OPTIONAL ).
IF ls_check is NOT INITIAL.
CONTINUE.
ENDIF.
data(ls_itabg) = ls_itab1.
CLEAR ls_itabg-code.
ls_itabg-quan = REDUCE i( INIT v = 0
FOR ls IN FILTER #( itab1 USING KEY grp
WHERE group = ls_itabg-group )
NEXT v = v + ls-quan ).
APPEND ls_itabg TO itabg.
CLEAR: ls_itabg,ls_check,ls_itab1.
ENDLOOP.
*4.2>复杂汇总 -- 按照code与group汇总
DATA itab2 TYPE TABLE OF ty_002
WITH NON-UNIQUE SORTED KEY cod COMPONENTS code group
WITH NON-UNIQUE SORTED KEY grp COMPONENTS group.
itab1 = VALUE #( ( code = '1' group = 'A' quan = 1 )
( code = '1' group = 'A' quan = 3 )
( code = '3' group = 'A' quan = 2 )
( code = '2' group = 'C' quan = 4 )
( code = '2' group = 'A' quan = 5 )
( code = '3' group = 'B' quan = 8 )
( code = '3' group = 'A' quan = 4 )
( code = '1' group = 'C' quan = 2 ) ).
"按照group汇总
DATA itabcg TYPE TABLE OF ty_002.
LOOP AT itab1 INTO ls_itab1.
ls_check = VALUE #( itabcg[ code = ls_itab1-code group = ls_itab1-group ] OPTIONAL ).
IF ls_check is NOT INITIAL.
CONTINUE.
ENDIF.
data(ls_itabcg) = ls_itab1.
CLEAR ls_itabg-code.
ls_itabg-quan = REDUCE i( INIT v = 0
FOR ls IN FILTER #( itab2 USING KEY cod
WHERE code = ls_itabcg-code
AND group = ls_itabcg-group )
NEXT v = v + ls-quan ).
APPEND ls_itabcg TO itabcg.
CLEAR: ls_itabcg,ls_check,ls_itab1.
ENDLOOP.
*&----------------------------------------------------------------------
* 练习四:OPEN SQL
*&---------------------------------------------------------------------*
cl_demo_output=>write( '练习四:' ).
*1> 工资大于等于1000为
* ... CASE WHEN sql_cond1 THEN result1
* [WHEN sql_cond2 THEN result2]
* [WHEN sql_cond3 THEN result3]
* ...
* [ELSE resultn]
* END ...
SELECT id,name,salary,
CASE WHEN salary GE 10000 THEN 'A'
WHEN salary GE 5000 AND salary LT 9999 THEN 'B'
WHEN salary LT 5000 THEN 'C'
ELSE ' ' END AS salary_1
FROM ytest_ng
* GROUP BY id,name,salary
INTO TABLE @DATA(gt_out_s).
cl_demo_output=>write( gt_out_s ).
SELECT rank,
SUM( CASE WHEN education = '本科' THEN 1 ELSE 0 END ) AS sum_ben_num , "--本科人数
SUM( CASE WHEN education = '专科' THEN 1 ELSE 0 END ) AS sum_zhuan_num "--专科人数
FROM ytest_ng GROUP BY rank
INTO TABLE @DATA(gt_out_e).
cl_demo_output=>write( gt_out_e ).
*&---------------------------------------------------------------------*
*CORRESPONDING关键字
*关键字MAPPING指定不同的字段赋值
*关键字EXCEPT排除某个字段不赋值
*&---------------------------------------------------------------------*
"1.工作区中相同字段赋值,可以省去不同字段赋值的语句
DATA:BEGIN OF ls_data1,
fd1 TYPE char10,
fd2 TYPE char10,
fd3 TYPE char10,
END OF ls_data1.
DATA:BEGIN OF ls_data2,
fd1 TYPE char10,
fd2 TYPE char10,
fd4 TYPE char10,
END OF ls_data2.
ls_data1 = VALUE #( fd1 = |First|
fd2 = |Second|
fd3 = |Third| ).
"类似MOVE-CORRESPONDING
ls_data2 = CORRESPONDING #( ls_data1 ).
WRITE: / |FD1:|,ls_data2-fd1,|FD2:|,ls_data2-fd2,|FD4:|,ls_data2-fd4.
SKIP.
"相同字段赋值的基础上,指定把ls_data1-fd3赋值给ls_data2-fd4
ls_data2 = CORRESPONDING #( ls_data1 MAPPING fd4 = fd3 ).
WRITE: / |FD1:|,ls_data2-fd1,|FD2:|,ls_data2-fd2,|FD4:|,ls_data2-fd4.
SKIP.
"相同字段赋值的基础上,排除fd2初始化
ls_data2 = CORRESPONDING #( ls_data1 EXCEPT fd2 ).
WRITE: / |FD1:|,ls_data2-fd1,|FD2:|,ls_data2-fd2,|FD4:|,ls_data2-fd4.
SKIP.
"相同字段赋值的基础上,指定把ls_data1-fd3赋值给ls_data2-fd4,fd2初始化
ls_data2 = CORRESPONDING #( ls_data1 MAPPING fd4 = fd3 EXCEPT fd2 ).
WRITE: / |FD1:|,ls_data2-fd1,|FD2:|,ls_data2-fd2,|FD4:|,ls_data2-fd4.
"2.内表相同字段赋值,可以省去LOOP中READ数据再赋值,只需要将不同的字段指定好
*DATA: LT_T001 TYPE STANDARD TABLE OF ACDOCA.
*
*SELECT
* BUKRS,
* BELNR,
* GJAHR,
* BUZEI
* FROM BSEG
* UP TO 3 ROWS
* INTO TABLE @DATA(LT_BSEG).
*
*"CORRESPONDING
*LT_T001 = CORRESPONDING #( LT_BSEG MAPPING RBUKRS = BUKRS
* DOCLN = BUZEI ).
*
*3.CORRESPONDING构造RANGE表,省去循环赋值,提高代码速度
RANGES: lr_rank FOR ytest_ng-rank.
lr_rank[] = CORRESPONDING #( gt_data[] MAPPING low = rank
EXCEPT * ).
SORT lr_rank BY LOW.
DELETE ADJACENT DUPLICATES FROM lr_rank COMPARING LOW.
DELETE lr_rank WHERE low is INITIAL.
lr_rank-sign = 'I'.
lr_rank-option = 'EQ'.
MODIFY lr_rank TRANSPORTING sign option WHERE low IS NOT INITIAL.
SELECT * from ytest_ng INTO TABLE gt_data WHERE rank in lr_rank.
*LCL_ALV->DISPLAY( ).
BREAK-POINT.
*--------------------------------------------------------------------*
*COND SWITCH 操作符
*在新语法中,可以使用COND、SWITCH来根据逻辑表达式或情况的不同确定指定变量的结果。
*COND SWITCH可以理解为IF CASE的替代语法,提高了代码可读性、简洁性
*--------------------------------------------------------------------*
DATA(time) = COND string(
WHEN sy-timlo < '120000' THEN |{ sy-timlo TIME = ISO } AM|
WHEN sy-timlo > '120000' THEN |{ CONV t( sy-timlo - 12 * 3600 ) TIME = ISO } PM|
WHEN sy-timlo = '120000' THEN |High noon|
* ELSE
).
WRITE: time.
DATA: LV_STRING TYPE STRING VALUE 's'.
"旧
IF LV_STRING is INITIAL.
LV_STRING = ' inittial'.
ELSEIF LV_STRING = 'K'.
LV_STRING = 'is k'.
*ELSE.
ENDIF.
LV_STRING = COND #(
WHEN LV_STRING IS INITIAL THEN ' inittial'
WHEN LV_STRING = 'K' THEN 'is k'
ELSE LV_STRING "如果前面条件均不满足,一定要回写LV_STRING值,否则LV_STRING值将被回写的空值覆盖
).
WRITE: LV_STRING.
*WHNE后面只能跟变量,类似 CASE 变量 when不同的值
DATA(a) = 11.
DATA(text) = SWITCH #( a
WHEN '11' THEN '11yyagd'
WHEN '12' THEN '12dkdkkd'
* ELSE
).
WRITE: text.
DATA: LV_STRING1 TYPE STRING VALUE 's'.
lv_string1 = switch #( lv_string1 "如果非a b c,lv_string将被返回的空值覆盖;
WHEN 'a' THEN 'is a'
WHEN 'b' THEN 'is b'
WHEN 'c' THEN 'is c'
).
WRITE: LV_STRING.
TYPES:
BEGIN OF result,
operand TYPE string,
result TYPE string,
fdpos TYPE sy-fdpos,
END OF result.
DATA results TYPE STANDARD TABLE OF result WITH EMPTY KEY.
DATA: f1 TYPE c LENGTH 5 VALUE 'BD ',
f2 TYPE c LENGTH 5 VALUE 'ABCDE'.
cl_demo_input=>new(
)->add_field( CHANGING field = f1
)->add_field( CHANGING field = f2 )->request( ).
results = VALUE #( BASE results
( operand = 'CO'
result = COND #( WHEN f1 CO f2 THEN abap_true )
fdpos = sy-fdpos ) ).
results = VALUE #( BASE results
( operand = 'CN'
result = COND #( WHEN f1 CN f2 THEN abap_true )
fdpos = sy-fdpos ) ).
results = VALUE #( BASE results
( operand = 'CA'
result = COND #( WHEN f1 CA f2 THEN abap_true )
fdpos = sy-fdpos ) ).
results = VALUE #( BASE results
( operand = 'NA'
result = COND #( WHEN f1 NA f2 THEN abap_true )
fdpos = sy-fdpos ) ).
results = VALUE #( BASE results
( operand = 'CS'
result = COND #( WHEN f1 CS f2 THEN abap_true )
fdpos = sy-fdpos ) ).
results = VALUE #( BASE results
( operand = 'NS'
result = COND #( WHEN f1 NS f2 THEN abap_true )
fdpos = sy-fdpos ) ).
results = VALUE #( BASE results
( operand = 'CP'
result = COND #( WHEN f1 CP f2 THEN abap_true )
fdpos = sy-fdpos ) ).
results = VALUE #( BASE results
( operand = 'NP'
result = COND #( WHEN f1 NP f2 THEN abap_true )
fdpos = sy-fdpos ) ).
cl_demo_output=>new(
)->write( |'{ f1 WIDTH = 5 }' operand '{ f2 WIDTH = 5 }'|
)->display( results ).
*用于BAPI输出消息时,可用于拼接于一行显示的消息返回结果中
* CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
* EXPORTING
* DOCUMENTHEADER = LS_DOCUMENTHEADER
* IMPORTING
** OBJ_TYPE =
* OBJ_KEY = LV_KEY
** OBJ_SYS =
* TABLES
* ACCOUNTGL = LT_ACCOUNTGL
* ACCOUNTRECEIVABLE = LT_ACCOUNTRECEIVABLE
** ACCOUNTPAYABLE = LT_ACCOUNTPAYABLE
* CURRENCYAMOUNT = LT_CURRENCYAMOUNT
* EXTENSION2 = LT_EXTENSION2
* RETURN = LT_RETURN.
*
* LOOP AT LT_RETURN INTO DATA(LS_RETURN) WHERE TYPE CA 'AEX'.
* LS_OUT-MESSAGE =
* COND #( WHEN LS_OUT-MESSAGE = SPACE THEN LS_RETURN-MESSAGE
* ELSE |{ LS_OUT-MESSAGE }/{ LS_RETURN-MESSAGE }| ).
* ENDLOOP.
*--------------------------------------------------------------------*
*LOOP……GROUP BY
*--------------------------------------------------------------------*
DATA BEGIN OF gs_data1.
DATA: sss TYPE CHAR1,
char TYPE char1,
num TYPE i ,
end of gs_data1.
DATA: gt_data1 LIKE TABLE OF gs_data1.
DATA LV_COUNT TYPE I.
*内部追加赋值
gt_data1 = VALUE #( base gt_data1 ( sss = '1' char = 'A' )
( sss = '1' char = 'A' )
( sss = '2' char = 'A' )
( sss = '2' char = 'A' )
( sss = '3' char = 'A' )
( sss = '4' char = 'C' )
( sss = '5' char = 'A' )
( sss = '5' char = 'A' )
( sss = '2' char = 'A' )
( sss = '2' char = 'A' )
( sss = '3' char = 'B' )
( sss = '5' char = 'A' )
( sss = '5' char = 'A' )
( sss = '5' char = 'A' ) ).
*--------------------------------------------------------*
"按照相同sss,char的分组排序编号给num字段赋值
*--------------------------------------------------------*
SORT gt_data1 by sss char.
LOOP AT gt_data1 INTO gs_data1 GROUP BY ( sss = gs_data1-sss "循环时gs_data没有数据,数据通过分组到<L_MEMBER>,如果给gt_data赋值,也是用<L_MEMBER>,指针不用MODIFY
char = gs_data1-char
size = GROUP SIZE "size是本组条目数量
index = GROUP INDEX ) "INDEX组索引
ASCENDING
ASSIGNING FIELD-SYMBOL(<l_group>). "双击可以看到,size,index以及按条件分组的条件字段值
CLear lv_count.
LOOP AT GROUP <l_group> ASSIGNING FIELD-SYMBOL(<l_member>).
lv_count = lv_count + 1.
<l_member>-num = lv_count.
ENDLOOP.
ENDLOOP.
BREAK-POINT.
*--------------------------------------------------------*
"按照相同sss,char为一组,累加数据字段,并合并重复项
*--------------------------------------------------------*
DATA :gt_data_temp LIKE gt_data1,
gs_data_temp LIKE gs_data1.
SORT gt_data1 by sss char.
LOOP AT gt_data1 INTO gs_data1 GROUP BY ( sss = gs_data1-sss
char = gs_data1-char
size = GROUP SIZE
index = GROUP INDEX )
ASCENDING
ASSIGNING <l_group>.
CLear lv_count.
LOOP AT GROUP <l_group> ASSIGNING <l_member>.
lv_count = <l_member>-num + lv_count.
gs_data_temp = <l_member>.
ENDLOOP.
gs_data_temp-num = lv_count.
APPEND gs_data_temp to gt_data_temp.
CLEAR gs_data_temp.
ENDLOOP.
BREAK-POINT.
DATA lv_netwr TYPE vbak-netwr.
DATA: BEGIN OF lt_vbak_temp OCCURS 0,
vkgrp LIKE vbak-vkgrp,
vkbur LIKE vbak-vkbur,
netwr LIKE vbak-netwr,
waerk LIKE vbak-waerk,
END OF lt_vbak_temp.
*DATA lt_vbak_temp TYPE TABLE OF vbak WITH HEADER LINE.
SELECT *
FROM vbak
INTO TABLE @DATA(lt_vbak)
UP TO 100 ROWS.
SORT lt_vbak BY vkgrp vkbur.
LOOP AT lt_vbak INTO DATA(ls_vbak)
GROUP BY ( vkgrp = ls_vbak-vkgrp
vkbur = ls_vbak-vkbur
waerk = ls_vbak-waerk
size = GROUP SIZE
index = GROUP INDEX )
ASCENDING
ASSIGNING FIELD-SYMBOL(<group>).
LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<member>).
TRY.
ADD <member>-netwr TO lv_netwr.
CATCH cx_sy_arithmetic_error.
ENDTRY.
MOVE-CORRESPONDING <member> TO lt_vbak_temp.
ENDLOOP.
lt_vbak_temp-netwr = lv_netwr.
APPEND lt_vbak_temp.
CLEAR: lt_vbak_temp,lv_netwr,ls_vbak.
ENDLOOP.
cl_demo_output=>write( lt_vbak_temp[] ).
cl_demo_output=>display( ).
*&---------------------------------------------------------------------*
*& Report YTEST_NEW_GRAMMAR_AN2
*&---------------------------------------------------------------------*
*&SAP SQL杂项函数
*select 与 case结合使用最大的好处有两点,一是在显示查询结果时可以灵活
*的组织格式,二是有效避免了多次对同一个表或几个表的访问
*&---------------------------------------------------------------------*
REPORT ytest_new_grammar_an2.
*连接字符串的两种写法
DATA(lv_date1) = sy-datum && sy-uzeit.
DATA(lv_date2) = |{ sy-datum(4) - 1 }{ sy-datum+4 + 1 }|.
*cl_demo_output=>write( lv_date1 ).
*cl_demo_output=>write( lv_date2 ).
SELECT COUNT( DISTINCT carrid )
FROM spfli
WHERE cityto = 'NEW YORK'
INTO @DATA(count).
*cl_demo_output=>write( count ).
SELECT *
FROM scustom USING CLIENT '100'
INTO TABLE @DATA(lt_customers).
*cl_demo_output=>write( lt_customers ).
*1. ... CASE operand
* WHEN operand1 THEN result1
* [WHEN operand2 THEN result2]
* ...
* [ELSE resultn]
* END ...
DELETE FROM demo_expressions.
INSERT demo_expressions FROM TABLE @( VALUE #(
( id = 'x' char1 = 'aaaaa' char2 = 'bbbbb' )
( id = 'y' char1 = 'xxxxx' char2 = 'yyyyy' )
( id = 'z' char1 = 'mmmmm' char2 = 'nnnnn' ) ) )
ACCEPTING DUPLICATE KEYS.
DATA(else) = 'fffff'.
SELECT id, char1, char2,
CASE char1
WHEN 'aaaaa' THEN concat( char1 , char2 )
WHEN 'xxxxx' THEN substring( char1,1,2 )
ELSE @else
END AS text
FROM demo_expressions
INTO TABLE @DATA(lt_results1).
*cl_demo_output=>write( lt_results1 ).
"实际应用
SELECT c~bukrs, b~werks, a~budat, b~matnr, h~maktx, e~waers,
c~lifnr, g~name1, g~land1, i~aplfz, b~meins,
CASE b~kzabs
WHEN 'X' THEN 'VMI'
ELSE ' '
END AS kzabs1,
CASE substring( c~zterm,1,1 )
WHEN 'B' THEN 'BWT'
ELSE ' '
END AS zterm1,
SUM(
CASE a~shkzg
WHEN 'S' THEN ( a~dmbtr )
WHEN 'H' THEN ( a~dmbtr * -1 )
END ) AS dmbtr1,
SUM(
CASE a~shkzg
WHEN 'S' THEN ( b~menge )
WHEN 'H' THEN ( b~menge * -1 )
END ) AS menge,
CASE e~waers
WHEN 'KRW' THEN 100
WHEN 'JPY' THEN 100
WHEN 'VND' THEN 100
ELSE 1
END AS factor
FROM ekbe AS a
INNER JOIN ekpo AS b
ON b~ebeln = a~ebeln
AND b~ebelp = a~ebelp
INNER JOIN ekko AS c
ON c~ebeln = a~ebeln
INNER JOIN t001k AS f
ON f~bwkey = b~werks
INNER JOIN t001 AS e
ON e~bukrs = f~bukrs
INNER JOIN lfa1 AS g
ON g~lifnr = c~lifnr
INNER JOIN makt AS h
ON h~matnr = a~matnr
INNER JOIN zm094v AS i
ON i~lifnr = g~lifnr
AND i~matnr = a~matnr
AND i~werks = a~werks
WHERE h~spras = 'E'
AND b~mtart = 'ROH'
GROUP BY c~bukrs, b~werks, a~budat, b~matnr, h~maktx,
e~waers, c~lifnr, g~name1, g~land1, i~aplfz,
b~meins, b~kzabs, c~zterm
INTO TABLE @DATA(gt_vmi).
*cl_demo_output=>write( gt_vmi ).
*--------------------------------------------------------------------*
*2. ... CASE WHEN sql_cond1 THEN result1
* [WHEN sql_cond2 THEN result2]
* [WHEN sql_cond3 THEN result3]
* ...
* [ELSE resultn]
* END ...
*CASE WHEN可以用大于,小于,SUBSTRING,CONCAT,LIKE,BETWEEN,不能用IN ,EXISTS,等条件
DELETE FROM demo_expressions.
INSERT demo_expressions FROM TABLE @( VALUE #(
( id = 'w' char1 = 'vvvvv' char2 = 'wwwww' dec1 = 1018 dec2 = '11.11')
( id = 'x' char1 = 'aaa77' char2 = 'bbbbb' dec1 = 1018 )
( id = 'y' char1 = 'xxxxx' char2 = 'yyyyy' dec1 = 1118 )
( id = 'z' char1 = 'mmmmm' char2 = 'nnnnn' dec1 = -1218 )
( id = 'm' char1 = 'mmmmm' char2 = 'nnnnn' dec1 = 1318 dec2 = '12.12') ) )
ACCEPTING DUPLICATE KEYS.
SELECT id ,
CASE WHEN char1 LIKE '%a77' "LIKE
THEN ( char1 && char2 )
ELSE ( char2 && char1 )
END AS text
FROM demo_expressions
INTO TABLE @DATA(lt_a77).
*cl_demo_output=>write( lt_a77 ).
SELECT id ,
CASE WHEN substring( char1,3,3 ) = 'a77' "SUBSTRING
THEN ( char1 && char2 )
ELSE concat( char2 ,char1 ) "CONCAT
END AS text
FROM demo_expressions
INTO TABLE @DATA(lt_a77_sub).
*cl_demo_output=>write( lt_a77_sub ).
SELECT id ,
* case when ( char1 && '%' ) = 'aaa77%'
CASE WHEN concat( char1 , '%' ) = 'aaa77%'
THEN ( char1 && char2 )
ELSE concat( char2 , char1 )
END AS text
FROM demo_expressions
INTO TABLE @DATA(lt_a77_con).
*cl_demo_output=>write( lt_a77_con ).
SELECT id,ceil( dec2 ) AS dec2_ceil,floor( dec2 ) AS dec2_floor,
CASE WHEN dec1 BETWEEN 1101 AND 1130 "ONLY Numerical type
THEN 'BETWEEN'
WHEN abs( dec1 ) = 1218 THEN 'ABS'
ELSE 'others'
END AS text_dec1,
CASE WHEN ceil( dec2 ) = 12 THEN 'CEIL'
WHEN floor( dec2 ) = 12 THEN 'FLOOR'
ELSE 'OTHERS'
END AS text_dec2
FROM demo_expressions
INTO TABLE @DATA(lt_dec).
*cl_demo_output=>write( lt_dec ).
*--------------------------------------------------------------------*
GET TIME STAMP FIELD DATA(gv_timestamp).
DELETE FROM demo_expressions.
INSERT demo_expressions FROM @(
VALUE #( id = 'X' timestamp1 = gv_timestamp ) ).
*--------------------------------------------------------------------*
"CAST数据转换函数& div|mod|*|/|substring|concat等嵌套使用
*--------------------------------------------------------------------*
SELECT SINGLE
FROM demo_expressions
FIELDS CAST( CAST( div( timestamp1 , 1000000 ) AS CHAR )
AS DATS ) AS date,
CAST( substring( CAST( timestamp1 AS CHAR ), 9, 6 )
AS TIMS ) AS time
INTO @DATA(ls_expressions).
*cl_demo_output=>write( ls_expressions ).
*--------------------------------------------------------------------*
"fields与SINGLE的区别 & 日期类型与char类型显示的不同
*--------------------------------------------------------------------*
SELECT SINGLE CAST( div( timestamp1 , 1000000 )
AS CHAR )
AS date,
CAST( substring( CAST( timestamp1
AS CHAR ), 9, 6 )
AS TIMS ) AS time
FROM demo_expressions
INTO @DATA(ls_expressions1).
*cl_demo_output=>write( ls_expressions1 ).
DELETE FROM demo_expressions.
INSERT demo_expressions FROM TABLE @(
VALUE #( ( id = 'X' num1 = 111 )
( id = 'Y' num1 = 222 )
( id = 'Z' num1 = 333 ) ) ).
*--------------------------------------------------------------------*
"WHERE 中等号左右两边都可以使用CAST,SUBSTRING,CONCAT,*,+,-等
*--------------------------------------------------------------------*
*SELECT FROM demo_expressions
* FIELDS id, num1
* WHERE CAST( num1 AS CHAR ) LIKE '2%'
* INTO TABLE @DATA(result).
select t1~matnr,
werks,
charg,
cuobj
from mchb as t1
left outer join inob as t2
on substring( t2~objek , 1, 18 ) = t1~matnr "1-18位 是物料号
and substring( t2~objek, 41,10 ) = t1~charg "41~50位 是批次
where t2~klart = '023'
into table @data(lt_mchb).
SELECT *
FROM bkpf "AS t1
WHERE substring( awkey , 1, 10 ) = '1'
AND substring( awkey , 11, 4 ) = 1
INTO TABLE @data(gt_outt) .
SELECT *
FROM bkpf "AS t1
WHERE awkey = '___5555_' "假设共8位,想取4-7位数据为5555的
AND substring( awkey , 1, 4 ) = 1
INTO TABLE @data(gt_outtt) .
"SELECT…聚合函数&CAST
SELECT carrid, SUM( CAST( price AS DEC( 20,2 ) ) ) AS price1
FROM ysflight_oolav_1
WHERE carrid = 'JL'
GROUP BY carrid
INTO TABLE @DATA(lt_ysflight_oolav_1).
*cl_demo_output=>write( lt_ysflight_oolav_1 ).
*--------------------------------------------------------------------*
*case…when& concat& substring& cast嵌套使用
*CAST,SUBSTRING,CONCAT,*,+,-等也可以在CASE WHEN,THEN,WHERE关键字等号左右两边均可使用,
* CASE WHEN中小数怎么处理,可以给左边取数乘以10
*CAST也可用于同类型修改长度
*--------------------------------------------------------------------*
"Get Goal
GET TIME STAMP FIELD data(lv_start_time)."获取当前系统的时间戳
SELECT a~zcustg,
b~name,
a~goal_rate AS goal_deci,
a~gjahr,
" goal_rate = 0
CASE WHEN a~goal_rate = 0 THEN ' '
"goal_rate >=1
WHEN a~goal_rate >= 1
THEN concat( substring( CAST( ( a~goal_rate * 100 ) AS CHAR ),
1,3 ), '%' )
"0 < goal_rate < 0.1
WHEN ( a~goal_rate * 10 ) < 1 AND a~goal_rate > 0
THEN concat( substring( CAST( ( a~goal_rate * 100 ) AS CHAR ),
1,1 ), '%' )
"0.1 <= goal_rate < 1
ELSE concat( substring( CAST( ( a~goal_rate * 100 ) AS CHAR ),
1,2 ), '%' )
END AS goal
FROM zsa6202 AS a
INNER JOIN zsa6001 AS b
ON a~zcustg = b~zcustg
ORDER BY a~zcustg, b~name
INTO TABLE @DATA(lt_data) .
GET TIME STAMP FIELD data(lv_end_time).
DATA(lv_rfc_time) = lv_end_time - lv_start_time. "
GET TIME STAMP FIELD data(lv_start_time1)."获取当前系统的时间戳
SELECT a~zcustg,
b~name,
a~goal_rate AS goal_deci,
a~gjahr,
a~goal_rate
FROM zsa6202 AS a
INNER JOIN zsa6001 AS b
ON a~zcustg = b~zcustg
ORDER BY a~zcustg, b~name
INTO TABLE @DATA(lt_data1) .
GET TIME STAMP FIELD data(lv_end_time1).
DATA(lv_rfc_time1) = lv_end_time1 - lv_start_time1. "
*cl_demo_output=>write( lt_data ).
cl_demo_output=>write( lv_rfc_time ).
cl_demo_output=>write( lv_rfc_time1 ).
*--------------------------------------------------------------------*
*除了CAST、CONCAT之外,ROUND, LPAD, LENGTH, REPLACE, RIGHT, RTRIM,SUBSTRING
*等函数也可以使用,杂项函数COALESCE 也可以使用,但是最多255个表达式
*--------------------------------------------------------------------*
"LPAD可用于补0,或者补任何字符
SELECT CONCAT( CONCAT( carrid,
LPAD( carrname,30,' ' ) ),
LPAD( url,40,' ' ) ) AS line
FROM scarr
INTO TABLE @DATA(result1).
cl_demo_output=>write( result1 ).
DELETE FROM demo_expressions.
INSERT demo_expressions FROM TABLE @( VALUE #(
( id = 'X'
char1 = ' 0123'
char2 = ' 4567' ) ) ).
SELECT SINGLE
char1 AS text1,
char2 AS text2,
CONCAT( char1,char2 ) AS concat,
LENGTH( char1 ) AS length, "字符串长度,包含空格长度
"从左边去除字符串的所有空格,类似SHIFT <l_tbtco>-periode LEFT DELETING LEADING '0'.不止为0,可以为其他字符
LTRIM( char1,' ' ) AS ltrim,
LPAD( char1,10,'0' ) AS LPAD, "补0,或者补任何其他字符至10位
REPLACE( char1,'12','__' ) AS replace, "替换
RIGHT( char1,3 ) as right, "从右边截取,且包含空格
RTRIM( char1,'3' ) AS rtrim, ""该函数功能是在arg的右边查找char字符,如果找到,则去掉;
SUBSTRING( char1,3,3 ) AS substring
FROM demo_expressions
INTO @DATA(result2).
cl_demo_output=>write( result2 ).
*--------------------------------------------------------------------*
*REPLACE
*RIGHT( arg, len ) 从右往左截取固定长度
*RTRIM( arg, char ) 该函数功能是在arg的右边查找char字符,如果找到,则去掉;
*COALESCE( sql_exp1, sql_exp2, ..., sql_expn ) 凝聚函数,该函数的功能是将参数中的第一个不为空的参数返回来
*可以用于不同的表取值
*--------------------------------------------------------------------*
SELECT matnr,
replace( vpsta,'VE','HU' ) AS str,
vpsta,
ernam
FROM mara
WHERE vpsta LIKE 'KCV%'
INTO TABLE @DATA(gt_out) UP TO 10 ROWS.
SELECT matnr,
right( matkl,3 ) AS str,
matkl
FROM mara
WHERE vpsta LIKE 'KCV%'
INTO TABLE @DATA(gt_out1) UP TO 10 ROWS.
*其实该语法也可以用于inner join,从而可以解决在inner join时字段长度不一致的问题
SELECT a~*
FROM vbrp AS a
INNER JOIN ekpo AS b ON a~aubel = b~ebeln
AND right( a~aupos,5 ) = b~ebelp
WHERE b~ebeln <> ''
INTO TABLE @DATA(gt_out2).
*该函数的功能是将参数中的第一个不为空的参数返回来,或者是将参数中第一个成立的表达式的值返回到别名
*比如请假,先找cell长审批,再找part长,再找group长,再找team长,也可以innerjoin等
SELECT
FROM mara
FIELDS matnr,
coalesce( CASE vpsta WHEN 'KDG' THEN 'HUJIE' END,
CASE vpsta WHEN 'KDA' THEN 'LAIMIN'
ELSE 'DUODUO'
END ) AS str,
vpsta
WHERE vpsta LIKE 'KD%'
INTO TABLE @DATA(lt_out) UP TO 10 ROWS.
SELECT LFA1~LIFNR,
COALESCE( EKKO~LIFNR, EKKO~EBELN, '无采购订单' ) as vendor
FROM LFA1
INNER JOIN EKKO ON LFA1~LIFNR = EKKO~LIFNR
INTO TABLE @DATA(LT_OUT1).
cl_demo_output=>display( ).

【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)