There are 100 students and 7 subjects. how to calculate the average of each student . when student id is selected in selection screen it should display the average for that particular student .
source code
TYPES:
test_1 TYPE SORTED TABLE OF ztest_03
WITH UNIQUE DEFAULT KEY.
DATA:
it_test TYPE test_1,
wa_test LIKE LINE OF IT_TEST,
total(3) TYPE n,
average(2) TYPE n.
SELECT-OPTIONS:
std_id for wa_test-studentid.
PARAMETERS:
test_id TYPE ztest_03-test.
START-OF-SELECTION.
SELECT *
FROM ztest_03
INTO CORRESPONDING FIELDS OF TABLE it_test
WHERE test = test_id
and studentid in std_id.
IF sy-subrc <> 0.
MESSAGE A123(Z455).
ENDIF.
END-OF-SELECTION.
LOOP AT it_test INTO wa_test.
* WRITE: /
* wa_test-studentid.
* wa_test-subjectid,
* wa_test-test,
* wa_test-marks.
total = total + wa_test-marks.
at END OF studentid.
IF TEST_ID = 'FINALS'.
WRITE:/ 'Test FINALS Details for student ID:' , WA_TEST-STUDENTID.
ELSE.
WRITE:/ 'Test CYCLE TEST Details for student ID:', WA_TEST-STUDENTID.
ENDIF.
average = total / 7.
uline.
WRITE:/ WA_TEST-STUDENTID, 'Average %:', average.
if average Le 50.
write:/ 'Grade E'.
ULINE.
ELSEif average le 60.
write:/ 'Grade D'.
ULINE.
ELSEIF average le 70.
WRITE:/ 'Grade C'.
ULINE.
ELSEIF average le 80.
WRITE:/ 'Grade B'.
ULINE.
ELSEIF average le 90.
WRITE:/ 'Grade A'.
ULINE.
ELSEIF average le 100.
WRITE:/ 'Grade O'.
ULINE.
ENDIF.
ENDAT.
ENDLOOP.
Assuming your data is stored in the database, see SAP's help on AVG
Related
In a VERY nested SQL statement, I want to produce a decimal value with only 2 digits behind the decimal point. Here are 2 paragraphs from a large SQL program below. The statement I am having trouble with is this one: ROUND(((convert(decimal(11, 6), sum(pf1.NO_OF_RECONCILED_TRX)) / tot_tab.tot_trx) * 100.0),2) AS "% To Total Acct". I need the values in the "% To Total Acct" column to be as 58.82 instead of 58.820000000000000000.
Image of results is also attached
SELECT
a1.ACCOUNT_NUMBER
, a1.ACCOUNT_NAME
, ap1.PASS_ID
, isnull(ap1.PASS_NAME, 'Out') "Pass Name"
----, (convert(decimal(23, 6), sum(pf1.NO_OF_RECONCILED_TRX)) / tot_tab.tot_trx) * 100.0 "% To Total Acct"
, ROUND(((convert(decimal(11, 6), sum(pf1.NO_OF_RECONCILED_TRX)) / tot_tab.tot_trx) * 100.0),2) AS "% To Total Acct"
----, (convert(decimal(23, 6), sum(pf1.NO_OF_RECONCILED_TRX)) / tot_tab.tot_trx) "# Reconciled Items by Pass"
----, SUM (NO_OF_RECONCILED_TRX) as TotalRows
, SUM (NO_OF_RECONCILED_TRX) as "# Reconciled Items by Pass"
FROM
BRR_ACCOUNT_HIERARCHIES ah1
inner join BRR_ACCOUNTS a1 on ah1.ACCOUNT_ID = a1.ACCOUNT_ID
inner join BRD_PROPERTY prop on a1.ACCOUNT_ID = prop.ACCOUNT_ID and prop.USER_ID = 1952 and prop.PROPERTY_NAME = 'Allow Access' and prop.PROPERTY_VALUE = 'Yes'
inner join BRR_PASS_FACT pf1 on ah1.ACCOUNT_ID = pf1.ACCOUNT_ID
inner join BRD_DAY d1 on pf1.DAY_ID = d1.DAY_ID AND d1.DAY_ID > 15614 and d1.DAY_ID < 15695 --SEPT 30 & DEC 20TH
left outer join BRR_AUTOREC_PASSES ap1 on pf1.PASS_ID = ap1.PASS_ID
cross join
(...
RESULTS:
ACCOUNT_NUMBER ACCOUNT_NAME PASS_ID Pass Name % To Total Acct # Reconciled Items by "PASS NAME"
11003 11003 CASH IN TRANSIT-BRANCHES 57 GL (FAST) CO ACCT CENTER FULLREF 58.82000000000000000 24108
11003 11003 CASH IN TRANSIT-BRANCHES 37 GL 1-1 (AR) CO ACCT CENTER REF-NO(Full) 41.15000000000000000 16864
11003 11003 CASH IN TRANSIT-BRANCHES 697 GL 1-1 Co Acct Center Ext Ref not blank o or CIW 0.01000000000000000 6
11003 11003 CASH IN TRANSIT-BRANCHES 58 GL(1-1) AR CO-ACCT-CTR-SRC (CCMWO RESOLVE) 0.01000000000000000 6``
The commented-out the lines I tried using. The closest I came to what I need was from using the ROUND statement. It replaced the trailing numbers with trailing zeroes with the exception of the first 2 numbers behind the decimal point. I eliminated the numbers, but they were replaced by zeroes. For example, I need for the value to be as 58.82 instead of 58.8200000000000.
As Dale K mentioned, just change
ROUND(((convert(decimal(11, 6), sum(pf1.NO_OF_RECONCILED_TRX)) / tot_tab.tot_trx) * 100.0),2) AS "% To Total Acct"
to
CONVERT(DECIMAL(11,2),ROUND(((convert(decimal(11, 6), sum(pf1.NO_OF_RECONCILED_TRX)) / tot_tab.tot_trx) * 100.0),2)) AS "% To Total Acct"
For years, I have used the humble spreadsheet as a way of keeping track of finances, but as this spreadsheet grew in size, and as I required more types of data analyses, it eventually became clear that a spreadsheet was no longer going to cut it. Problem is, going from Calc to Base has been a slow learning process in understanding SQL (HSQLDB, specifically), particularly its syntax.
Below is an example table with some arbitrary values. We'll call it Table A. There are a lot of other columns in my original table, but are either irrelevant, or I have already figured out what to do with them.
Quantity
Account Paid From
Recipient A Percentage
Recipient B Percentage
100
A
100
0
200
B
0
100
500
A
0
100
50
B
100
0
10
A
40
60
The idea here is that in row 1, Person A paid for something intended solely for person A. Therefore, this transaction does not result in anyone owing anything to another person. Same with row 2, where person B paid for something intended solely for person B
In row 3, person A paid $500 on behalf of person B. Person B now owes Person A $500.
In row 4, B Paid $50 for A. Subtract 50 from 500, and B now only owes A $450
In row 5, A paid for something that is 40% theirs, and 60% for B. In other words, A paid $6 out of the $10 for B. B now owes A 500 - 50 + 6 $456
I'm looking for something along the lines of the following:
Select all entries where Account Paid From = A
Of those entries, take the total sum of Quantity * Recipient B Percentage / 100
The result is how much B owes A
Select all entries where Account Paid From = B
Of those entries, take the total sum of Quantity * Recipient A Percentage / 100
The result is how much A owes B
Subtract A owes B from B owes A to find out who is in debt to the other (if the value is + or -), and by how much.
I guess something along the lines of:
SELECT SUM("Account Paid From" * "Recipient B Percentage / 100)
WHERE "Account Paid From" = "A" - SUM("Account Paid From" * "Recipient B Percentage / 100)
WHERE "Account Paid From" = "B" AS "Owed"
FROM "Table A"
But...you know, without syntax errors screaming at me.
For simplicity, I will use table name "T" and the following abbreviated column names:
"Quantity" "Q", "Account Paid From" "APF", "Recipient A Percentage" "RAP", "Recipient B Percentage" "RBP"
SELECT * FROM T WHERE "APF" = 'A'
SELECT SUM("Q" * "RBP" / 100) AS "Sum RBP" FROM "T" WHERE "APF" = 'A'
SELECT SUM("Q" * "RAP" / 100) AS "Sum RAP" FROM "T" WHERE "APF" = 'B'
SELECT "Sum RBP" - "Sum RAP" FROM (SELECT SUM("Q" * "RBP" / 100) AS "Sum RBP" FROM "T" WHERE "APF" = 'A'), (SELECT SUM("Q" * "RAP" / 100) AS "Sum RAP" FROM "T" WHERE "APF" = 'B')
I wish to derive cumulative column based on initially adding the daily amount to the Value, then subsequently adding the daily amount to the resulting figure.
Could you please help, thanks.
Date
Type
Value
Rate
Cummulative
29/04/2022
A
128.61
32.00
256.61
28/04/2022
A
128.61
32.00
224.61
27/04/2022
A
128.61
32.00
192.61
26/04/2022
A
128.61
32.00
160.61
Have a look at the example script below. Once reloaded the CumulativeData table will contain new column Cumulative which will be the result.
The "magic" is happening in the following expression:
if(RecNo() = 1,
Value + Rate,
peek(Cumulative) + Rate
) as Cumulative
In the expression we are saying:
if the record number is 1 (first row of the table) then sum Value and Rate values. This is our "base" and we'll accumulate to this value
for the next rows get the above (previous row) value of Cumulative column (peek(Cumulative)) and add the current row Rate value
More about peek function can be found at the documentation page
Example script:
RawData:
Load * Inline [
Date , Type, Value , Rate
29/04/2022, A , 128.61, 32.00
28/04/2022, A , 128.61, 32.00
27/04/2022, A , 128.61, 32.00
26/04/2022, A , 128.61, 32.00
];
// Dont foget to order the table in ascending order
CumulativeData:
Load
*,
if(RecNo() = 1,
Value + Rate,
peek(Cumulative) + Rate
) as Cumulative
Resident
RawData
Order By
Date ASC
;
Drop Table RawData;
Result table:
My data looks like this:
Currency Price FX_Rate_MXN FX_Rate_BRL
MXN $5 .2 .5
BRL $7 .2 .5
I'd like to create a new column that will multiply "Price" by the correct exchange rate, depending on the currency in the "Currency" column. Any ideas?
You can use a case expression:
select t.*,
(case when currency = 'MX' then price * fx_rate_mxn
when currency = 'BRL' then price * fx_rate_brl
end) as price_in_currency
from t;
Of course, it is not clear if you want to multiply or divide by the fx rate.
My internal table looks like this:
Id vendor doc_no debit credit
Abc. Ven1. 123. 4000. 5000
Abc. Ven2. 345. 5000 6000
Abc. Ven1. 367. 8000. 9000
Abc. Ven2. 890. 3000. 8000
Now, I need to find the largest debit for each vendor. On the basis of above example, for vendor Ven1. largest debit will be (4000+8000) = 12000. Similarly for Ven2. vendor the largest debit value will be (5000+3000) = 8000.
How to achieve this??
Here is an example report containing the most performant solution I can think of. It's using the fairly new ABAP commands FOR GROUPS … IN and REDUCE. Just copy it in your system and give it a try.
REPORT Z_SUM_BY_VENDOR.
"Prepare test data
TYPES: BEGIN OF lty_st_data_source,
id TYPE C LENGTH 3,
vendor TYPE C LENGTH 4,
doc_no TYPE C LENGTH 3,
debit TYPE I,
credit TYPE I,
END OF lty_st_data_source.
DATA: lt_data_source TYPE STANDARD TABLE OF lty_st_data_source.
APPEND VALUE #( id = 'Abc' vendor = 'Ven1' doc_no = '123' debit = 4000 credit = 5000 ) TO lt_data_source.
APPEND VALUE #( id = 'Abc' vendor = 'Ven2' doc_no = '345' debit = 5000 credit = 6000 ) TO lt_data_source.
APPEND VALUE #( id = 'Abc' vendor = 'Ven1' doc_no = '367' debit = 8000 credit = 9000 ) TO lt_data_source.
APPEND VALUE #( id = 'Abc' vendor = 'Ven2' doc_no = '890' debit = 3000 credit = 8000 ) TO lt_data_source.
" Define type for sum table and generate sum (actual answer to the question)
TYPES: BEGIN OF lty_st_grouped,
vendor TYPE C LENGTH 4,
debit_sum TYPE I,
END OF lty_st_grouped,
lty_tt_grouped TYPE HASHED TABLE OF lty_st_grouped WITH UNIQUE KEY vendor.
DATA(lt_grouped) = VALUE lty_tt_grouped(
FOR GROUPS vendor_group OF <ls_data_source> IN lt_data_Source
GROUP BY <ls_data_source>-vendor
( VALUE lty_st_grouped( vendor = vendor_group
debit_sum = REDUCE i( INIT sum = 0
FOR <ls_data_source_2> IN GROUP vendor_group
NEXT sum = sum + <ls_data_source_2>-debit )
)
)
).
" Show result for demo purpose
LOOP AT lt_grouped ASSIGNING FIELD-SYMBOL(<ls_grouped>).
WRITE: `Vendor: ` && <ls_grouped>-vendor && ` | Debit Sum: ` && <ls_grouped>-debit_sum.
NEW-LINE.
ENDLOOP.
Create a structure with your required fields in the correct order of dimension(s) and measures. Then you can savely use the "AT" functions, aggregating your debit for each "group of" vendors.
DATA: Begin of ls_itab_ordered
vendor type vendor,
debit type debit,
End of ls_itab_ordered,
lt_itab_ordered like standard table of ls_itab_ordered,
lt_itab_agg like itab.
move-corresponding itab to lt_itab_ordered
sort lt_itab_ordered by vendor.
loop at lt_itab_ordered assigning <ls_itab_ordered>.
at new vendor.
ls_itab_agg-vendor = <ls_itab_ordered>-vendor.
endat.
add <ls_itab_ordered>-debit to ls_itab_agg-debit.
at end of vendor.
append ls_itab_agg to lt_itab_agg.
clear ls_itab_agg.
endat.
endloop.
You can use Collect -
I'm considering it_vendor is your internal table and declare ls_vendor like it_vendor.
TYPES: BEGIN OF ty_calc,
vendor TYPE vendor, " (check DE of vendor then use that)
debit TYPE int4,
END OF ty_calc.
DATA: ls_calc TYPE ty_calc,
lt_calc TYPE TABLE OF ty_calc.
LOOP AT it_vendor INTO ls_vendor.
ls_calc-vendor = ls_vendor-vendor.
ls_calc-debit = ls_vendor-debit.
COLLECT ls_calc INTO lt_calc.
CLEAR : ls_calc , ls_vendor.
ENDLOOP.
Internal table lt_calc holds the largest debit for each vendor.