I have following select:
SELECT FROM bseg
LEFT JOIN aufk ON ( ltrim( aufk~aufnr, '0' ) = bseg~zuonr )
JOIN bkpf ON bkpf~belnr = bseg~belnr AND bkpf~gjahr = bseg~gjahr AND bkpf~bukrs = bseg~bukrs
FIELDS bseg~bukrs, bseg~bschl, bseg~wrbtr, bseg~h_hwaer
INTO TABLE @DATA(output).
When the select is complete I loop over the output
table making a calculation when bschl = '50'
.
LOOP AT output ASSIGNING FIELD-SYMBOL(<output>) WHERE bschl = '50'.
<output>-wrbtr = <output>-wrbtr * ( -1 ).
ENDLOOP.
Since ABAP 7.4 I could use CASE
statements in the SQL select.
This is what I want to use to get rid of the loop.
SELECT FROM bseg
LEFT JOIN aufk ON ( ltrim( aufk~aufnr, '0' ) = bseg~zuonr )
JOIN bkpf ON bkpf~belnr = bseg~belnr AND bkpf~gjahr = bseg~gjahr AND bkpf~bukrs = bseg~bukrs
FIELDS bseg~bukrs,
CASE
WHEN bseg~bschl = '50' THEN bseg~wrbtr * ( -1 )
ELSE bseg~wrbtr
END AS bseg~wrbtr, bseg~h_hwaer
INTO TABLE @DATA(output).
This is on how I would deal with the requirements described above.
Unfortunately I get an error message:
The maximum possible number of places in the expression starting with WRBTR is 34 places with 2 decimal places.
There can be, however, no more than 31 places and 14 decimal places.`
I also tried to cast bseg~wrbtr
:
WHEN bseg~bschl = '50' THEN CAST( bseg~wrbtr * ( -1 ) )
-> ")" is invalid here (due to grammar).
Or
WHEN bseg~bschl = '50' THEN CAST( bseg~wrbtr AS test ) * ( -1 )
-> "TEST" is invalid here (due to grammar).
Does someone know how to deal with this?
My answer is specific to setting a sign via * -1
. It doesn't apply to multiplications with other numbers.
In ABAP 7.52 and S/4HANA 1709, BSEG-WRBTR
is still a packed-7-bytes number including 2 decimals, and except END AS bseg~wrbtr
which leads to the error "~" is invalid here (due to grammar)
and must be replaced with END AS wrbtr
, the syntax is valid in my system.
In my system, the inline declaration of the output table chooses a packed-13-bytes number including 2 decimals. It's the multiplication that makes the number of digits in the output table multiplied by 2 (from 7 bytes to 13 bytes). As a comparison, an addition would only declare a packed-8-bytes number.
I guess you have a more recent S/4HANA version with BSEG-WRBTR
having many more digits (feature called "Amount Field Length Extension"), it's why the multiplication makes the inline declaration produces an invalid type with too many digits.
Workaround: if you sign without multiplying, it will keep the same number of digits (packed-7-bytes number in my case), and this syntax should also work in your case:
CASE bseg~bschl
WHEN '50' THEN - bseg~wrbtr "<=== negative sign, is not the same logic as * -1
ELSE bseg~wrbtr
END AS wrbtr
EDIT Dec 30th - I didn't find a clear reference in the ABAP documentation how the inline types are calculated for arithmetic SQL expressions, it's by searching "up" from the behavior I experienced that I could find a logical way "down":
The ABAP type to which the result type of an SQL expression is assigned is used for this expression.
Alongside any integer operands (see above), decimal expression have at least one operand with the type DEC, CURR, or QUAN or p with decimal places. The operator / is not allowed in decimal expressions. The result has the type DEC with the length 31 and a maximum of 14 decimal places. Using the associated assignment rule, it can be assigned to all numeric ABAP types whose value range is large enough, except for decimal floating point numbers.
If the target field has a numeric data type, the value of the result field is converted to this data type and the value range of the target field must be large enough. Here, any surplus decimal places in result fields of the type CURR, DEC, or QUAN (numbers in the BCD format) are cut off.