Warning: I have limited knowledge of tables!
I have a COBOL program that calculates GPAs on the fly in the OUTPUT section of the program. I have to store these on-the-fly GPAs in a table, and then sort them by school, grade level, GPA total, then student id. I can load my table, but I am not sorting it.
01 GPATBL. 03 GPAENTRY OCCURS 5000 TIMES ASCENDING KEYS GPACT1 GPAGRD GPATOTAL INDEXED BY GPA1 GPA2. 05 GPASCHOOL PIC X(04). 05 GPAGRADE PIC X(02). 05 GPATOTAL PIC S9(01)V9999. 05 GPASTUDENT PIC X(10). 05 GPANAME PIC X(33).
I load the table right after the GPA is calculated on-the-fly. The program is already sorting the basic data that was gathered in the INPUT section (school, grade, student number, and name (GPA is calculated on-the-fly in the OUTPUT section). So my table is being loaded by school, grade level, student id as the data is released from the sort record in the OUTPUT section.
How do I sort my table by school, grade level, GPA, then student number? I've looked at other forums and read about bubble sorts, sort verb, etc, but none of it makes any sense to me. I have read two COBOL books with chapters on tables and sorting. I think I need to do the "bubble sort", but I dont know where to begin. I follow the logic behind it (ascending key): store the 1st value, then check the 2nd value to see if its great than the 1st stored value, if it is, move 2nd value into table slot 2 else move 1st value to table slot 2 and store 2nd value in table slot 1.
Please help!!
Software/Hardware used:
iSeries Pwr6, IBM COBOL/400 compiler
ASKED:
February 18, 2011 9:38 PM
UPDATED:
March 2, 2011 3:17 PM
This is tagged with “COBOL/400″. If at all possible, you should be using ILE COBOL instead. I’d normally guess that you don’t realize there are significant differences, so it was probably just habit. Just to be sure, do you know if this really is “COBOL/400″? As far as SORT goes, I’m not sure the two compilers handle things differently, but it might be relevant.
Are you wanting to write your own sorting routine or do you want to use the COBOL SORT capability? They will turn out very different. And ILE COBOL can even make use of qsort (and other possibilities) if that’s your objective.
Tom
When I look at my spool file after compiling, it is listed as being IBM COBOL/400 across the top. I was under the impression that this is where you can find your compiler information. If there is somewhere else I should look for the compiler, I don’t know where to look.
I dont think I can use the COBOL SORT on this as I am building the table on the OUTPUT side and have already used the SORT on the input side. Maybe I am not understandign what you are asking there.
My objective is to take the data I have managed to load into a table and print it in the sorted order needed. How ever I can arrive at that path is better than what I have now!
Thx!
I forgot to mention that the compile listing also has:
Compiler . . . . . . . . . . . . . . : IBM COBOL/400
I have no choice in the compiler I use.
I dont think I can use the COBOL SORT on this as I am building the table on the OUTPUT side and have already used the SORT on the input side. Maybe I am not understandign what you are asking there.
Can you show the SORT code that you already have? If you’re already using SORT, why not sort in the order that you need at that time? Are you trying to sort in a different order after loading your table? Are you going to sort in an order that doesn’t match the ASCENDING/DESCENDING keys assigned on your table?
Note that you can have multiple SORT statements in your program.
Compiler . . . . . . . . . . . . . . : IBM COBOL/400
If you are at V6R1 or later, you might only have the one compiler available. Before V6R1, both versions are supplied but not necessarily loaded on the system by system administrators. The non-ILE compilers are slowly being phased out of IBM’s development plans.
A simple test of whether or not the ILE compiler is available is to see if the CRTBNDCBL command works to compile source and create a program.
Tom
The reason I am not sorting on the input side is because GPA is not a stored field like all the other data I am sorting. I have to calculate the GPA in the output side once the sorted records are returned. If GPA could be calculated on the input side or was a stored field, I would just sort it in the input. All the other information I am storing in my table is already sorted, but I have to sort by GPA first. For example, the data loads into my table like this:
My School 08 Smith Jane 3.5432
MySchool 08 Smith Joe 3.6000
But I need to get the data to print like this:
MySchool 08 Smith Joe 3.6000
MySchool 08 Smith Jan 3.5432
I am dealing with multiple schools and multiple grade levels as well. So I have to sort by school, grade, GPA, student identifier. So every body at MySchool in the 8th grade, should be listed in descending order by GPA. Everybody at MySchool in the 7th grade should be listed in descending order by GPA, etc.
Tomorrow I will try the CRTBNDCBL command. I highly doubt we have both compilers installed, but it’s worth a look.
ASCENDING KEYS GPACT1 GPAGRD GPATOTAL
Starting there, is that a typo? Neither GPACT1 nor GPAGRD is a subordinate element of the table. I assume that those refer to GPASCHOOL and GPAGRADE, but just got missed at some point. It doesn’t really matter in discussing SORT, so that might be ignored for now. Usually, the only reason to code the ASCENDING/DESCENDING KEYS clause is if you’re going to be using a SEARCH statement. If you’re not doing any SEARCHing for elements in the table, there’s no real use for ASCENDING/DESCENDING KEYS.
GPA is calculated on-the-fly in the OUTPUT section
Why? That is, why not on the INPUT side?
Most likely, it has to do with something like other values not being available until you’ve already sorted records so that everything is together for an individual student. For example, maybe you have to process multiple records per student in order to calculate GPA and you can’t do that until after the sorting is done. So, your INPUT side is receiving sets of detail records in order to group by school, grade and student; and your OUTPUT side is summarizing and creating single table entries per student including a calculated GPA (per student).
When that’s done, you now need to re-SORT in order to include GPA in the secondary SORT specifications. Am I understanding close enough?
If so, one answer is simply to have a second SORT that feeds table elements into the INPUT side and stores the results back in the table on the OUTPUT side.
But maybe there’s a better way. Think about possible alternatives.
Generally speaking, almost nobody does “sorts” of any kind on AS/400s nowadays. The system can do it automatically for you too easily. If you’re feeding file data into the SORT that you currently have, you possibly should skip that step entirely. Maybe you should simply create a VIEW/INDEX (or a “logical file”) that automatically gives you the records in sequence by school and grade and student. No need for “sort” in that case. The records will be already sorted when you read them — and none of the physical data will be changed; it’ll only be “logical data”.
It even seems possible to create a VIEW that summarizes and calculates GPA per student automatically. You possibly don’t need a COBOL program (or any program) at all for that much of the process.
In short, you can probably code a second SORT that uses an INPUT and an OUTPUT procedure to re-sort your table after calculating GPAs. Alternatively, you might define some database rules to have the database do some of the logical work to replace parts or (perhaps) all of the program.
If you use a second SORT, you might find it best to use REDEFINES to create an alternative definition over GPATBL. It might be useful to be able to refer to the same memory area with two different sets of ASCENDING keys. However, the real use of the keys is when you need to run SEARCH statements. If you aren’t doing any SEARCHing, then there’s usually no reason to code the ASCENDING/DESCENDING KEYs clause.
Most likely, it has to do with something like other values not being available until you’ve already sorted records so that everything is together for an individual student. For example, maybe you have to process multiple records per student in order to calculate GPA and you can’t do that until after the sorting is done. So, your INPUT side is receiving sets of detail records in order to group by school, grade and student; and your OUTPUT side is summarizing and creating single table entries per student including a calculated GPA (per student).
Yes, close enough. I don’t understand what you mean about feeding my table back into the INPUT side. I am processing returned SORT records, one student at a time, in the OUTPUT section to print a report. Someone has come along and doesnt like the report because they cannot sort the report by GPA. I was asked to take the data being produced (minus a few things), put it in a table, sort the table (by school, grade, GPA, student) without creating another physical file or adding another report, etc. They want to submit the current job (no changes) and just “enhanced” to have a “summary” printed from this new table I make. If, by some magical feet, I did manage to feed this table back into the SORT on the INPUT side, won’t I mess up the current sort I have going and screw up the report? I haven’t processed all my SORT records by the time I create the table. The table is being built one student at a time per returned SORT record.
The ascending keys on the table – I was told those would “sort” my data for me. Like I initially said, I have limited table knowledge, so I was like, ok. Yeah, it doesn’t work like that though! No magically solution there. I have already taken that off.
If, by some magical feet, I did manage to feed this table back into the SORT on the INPUT side, won’t I mess up the current sort I have going…
Going with the re-SORT scenario, you would code a second SORT statement that followed the first one. Without seeing your existing SORT statement, it’s difficult to describe in detail.
You have a SORT statement that references some OUTPUT procedure. In general, you would do something like:
That is, you wouldn’t feed it “back into” the SORT; you’d feed it into a second SORT.
The first part of that depends on how much code there is in the existing OUTPUT proc. I don’t know if the existing OUTPUT proc only places elements in the table or it includes all of the code for calculating GPA and producing the report. If the current OUTPUT proc contains all of the code for calculation and reporting, then it probably needs to be split into two parts.
Paragraphs that do the reporting would no longer be part of the OUTPUT proc for the first SORT. They wouldn’t be referenced until the OUTPUT proc of the new second SORT (or after the second SORT completes if they are not included in the first SORT’s OUTPUT now.)
They want to submit the current job (no changes) and just “enhanced” to have a “summary” printed from this new table I make.
I just read back over that part again. If I understand that correctly, then maybe you just add the second SORT after finishing the first report. The second SORT would sort the table again. After it completes, you loop through the table to create the “summary” report.
You might include the “summary” reporting in the second SORT’s OUTPUT proc, though I would try to keep the actual reporting separated from the sorting. I’d try to only RETURN sorted elements into the table in my SORT. The sorting and reporting are two different logical functions.
…without creating another physical file or adding another report,..
Just for clarification, defining a VIEW (or logical file) wouldn’t create any physical file. It simply creates a new “name” for you to use. By using the new name, the database knows that it should automatically provide the same ‘physical’ data in a different ‘logical’ form. The data itself doesn’t change in any way and everything that uses the original name continues working as always.
But I understand that that’s not the way you’re going.
The part about “another report”, though, is potentially confusing. Do you mean that the “summary” report should be nothing more than additional lines at the end of the current report? Or that these new sorted lines should replace the ones that are currently printed?
Tom
I was asked to take the data being produced (minus a few things), put it in a table, sort the table (by school, grade, GPA, student)…
Does that mean that the program had no SORT in it when you started?
Tom
Sorry for the confussion. The summary is just supposed to be added to the existing report. It is not replacing it. I have an option for the operator to include or exclude the GPA summary. It is supposed to print after each report break. I’ve written all my regular detail to the print line, then I break the report at MySchool grade 07- the GPA summary is supposed to print just the GPA summary for MySchool grade 07. Then the program goes back to printing out the report as it currently is by school, grade, student for the next group (MySchool grade 08). Then when I break at MySchool grade 08, another GPA summary is to print just for MySchool grade 08. It’s not just printing at the end of the report when all the other processing is done. It’s a summary at break.
The SORT for the regular report is set up like this:
SELECT SRT-RPT ASSIGN WORKSTATION-SORT. ... SD SRT-RPT. 01 SRT. 05 SRTKEY. .... SORT SRT-RPT ASCENDING KEY SRTKEY INPUT PROCEDURE 000-INPUT OUTPUT PROCEDURE 500-OUTPUT STOP RUN.If I create something similar to this but call it SRT-GPA, I can use it to sort this data? I’ve only ever seen the SORT with the procedure stuff done at the beginning of the procedure division. Can it be done anywhere in that division?
Well I just answered that question. I coded a separate SORT almost exactly like my code in the previous posting, but when I tried to RELEASE the 2nd sort, I got an error.
I call my table load routine as the INPUT where I branch off and load the 2nd SORT. I call my SORT return routine as the OUTPUT for the 2nd SORT. Both of these routines are in the OUTPUT section.
Both of these routines are in the OUTPUT section.
A SORT cannot be contained within the scope of another SORT.
That kind of relates to my earlier comment that I would keep any code related to summarizing or reporting outside of actual sorting.
I’ll see if I can create a sample code structure later this evening.
Tom
Time was up so I had to do a crappy shell sort. It isn’t pretty, efficient, or very self explanatory, but it works. I was just hoping I could find something better than that to use.
Thanks for trying to help, Tom.