2-Dimension Tables in COBOL

Sometimes the data that we need does not lend itself to a simple one dimension table - we need two dimensions. For example, reading distances on a map require that we know where we are starting and where we are going.

In the example to illustrate 2-Dimensional tables, assume that we want to know the fares from Boston to Chicago, Atlanta, and Austin for both tourist and first class. If all we wanted to know was the fares to the three destinations, a one dimensional table would work. But, when the extra dimension of knowing the fare for both tourist and first class is included, we will need a two dimension table. For our example we will assume that Chicago has a code of 1, Atlanta has a code of 2 and Austin has a code of 3. We will also assume that tourist has a code of 1 and first class has a code of two.

  Tourist (1) First Class (2)
Chicago (1) 349.79 499.50
Atlanta (2) 150.00 299.95
Austin (3) 389.00 550.00

The data on the input record has a code for destination and a code for class. The legal codes in the destination field are 1, 2, and 3 to stand for the three destinations and the legal codes in the class field are 1 and 2 to stand for the two classes.

01  INPUT-REC.
    ...
    05  CLASSZ          PIC 9.
    05  DESTINATIONZ    PIC 9.
The table would be setup in WORKING-STORAGE in the following way:
01  RATE-TABLE.
    05  TOURIST.
        10  T-CHICAGO    PIC 999V99     VALUE 349.79.
        10  T-ATLANTA 	 PIC 999V99     VALUE 150.00.
        10  T-AUSTIN     PIC 999V99     VALUE 389.00.
    05  FIRST-CLASS.
        10  F-CHICAGO    PIC 999V99     VALUE 499.50.
	10  F-ATLANTA    PIC 999V99     VALUE 299.95.
        10  F-AUSTIN     PIC 999V99     VALUE 550.00.
01  RDF-RATE-TABLE REDEFINES RATE-TABLE.
    05  CLASS-GROUP      OCCURS 2 TIMES.
        10  RATE    	 PIC 999V99     OCCURS 3 TIMES.
Note that the names used on the 05 and for that matter on the 10 level are not required, I could have used FILLER or no data name. The names are their for clarification and are in fact a wise programming move because they will also clarify the table for anyone looking at the program.
When the programmer sets up a two dimension table, one of the dimensions is picked to describe first. In this example, class was chosen. This means that in defining the table, each of the two classes has its own 05 level. In this example they are called 05 TOURIST and 05 FIRST-CLASS. Each of these 05 levels will be broken down as the second dimension is defined on the 10 level. (Remember the rule that PIC is only used on the lowest level, so because the 05 is being broken down there are no pictures on the 05 level.) Since there are three destinations in both classes, each of the 05 levels has three 10 levels beneath it, one for each destination. For example, under the 05 TOURIST, there are 10 T-CHICAGO, 10 T-ATLANTA, and 10 T-AUSTIN. Each of these is given a PIC and a VALUE.

In the redefinitions, this structure is continued. The 05 CLASS-GROUP OCCURS 2 TIMES because in the original layout there were two 05s. Each of these 05s now has another name CLASS-GROUP. Beneath each of the 05s there were three 10 level elements so beneath 05 CLASS-GROUP we see the 10 level RATE which OCCURS 3 TIMES and has a PIC corresponding to the 10 level pictures in the original data layout.

It is important to see the connection between the 05s in the original data layout and the 05 in the redefinition and the 10s in the original data layout and the 10s in the redefination because it helps to clarify the table layout. (Note that there are other ways to layout this table that would also work, but would sacrifice this clean connection.)

To use the RATE from the table, we must use the CLASSZ code and the DESTINATIONZ code as SUBSCRIPTs to point to the correct RATE. As you can see, there will be two SUBSCRIPTs, one for each dimension of the table. Since the first breakdown in the table (the 05 level) is for class, the SUBSCRIPT to select the correct class is the first subscript needed. If CLASSZ contains a 1, the CLASSZ subscript will point to the first 05 level (05 TOURIST) and if CLASSZ contains a 2, the CLASSZ subscript will point to the second 05 level (05 FIRST-CLASS). Now that the correct 05 level has been pointed to, the correct destination within that class is needed. For this, the DESTINATIONZ subscript is used to point to the correct 10 level. It is critical that the subscripts be used in the correct order - the first one points to the correct 05 level and the second one points to the correct 10 level.

If the goal is to move RATE to a field on the printline, then the MOVE statement to accomplish all this is:
	MOVE RATE (CLASSZ, DESTINATIONZ) TO RATE-PR.
Analyzing the move: In the example presented here, the decision was made to break the table down by class and destination within class. An alternative approach would have been to break the table down by destination and then class within destination.

01  RATE-TABLE.
    05  CHICAGO.
        10  CH-TOURIST   PIC 999V99     VALUE 349.79.
        10  CH-FIRSTCL   PIC 999V99     VALUE 499.50.
    05  ATLANTA.
        10  AT-TOURIST   PIC 999V99     VALUE 150.00
        10  AT-FIRSTCL   PIC 999V99     VALUE 299.95.
    05  AUSTIN.
        10  AU-TOURIST   PIC 999V99     VALUE 389.00.
        10  AU-FIRSTCL   PIC 999V99     VALUE 550.00.
01  RDF-RATE-TABLE REDEFINES RATE-TABLE.
    05  DESTINATION-GROUP       OCCURS 3 TIMES.
        10  RATE         PIC 999V99   OCCURS 2 TIMES.
In this table, the programmer decided to put destination at the 05 level and break each destination down into class. Since the first breakdown in the table (at the 05 level) is for destination, the DESTINATIONZ subscript is the first subscript or pointer that is used. If the DESTINATIONZ subscript is 1, the subscript will point to the first 05 level which is CHICAGO, 2 will point to ATLANTA, and 3 will point to AUSTIN. Once the pointer has selected the appropriate 05, the CLASSZ subscript can be used to select the correct class within that destination. Assuming the goal is to move the RATE to a field on the printline called RATE-PR, the MOVE statement will be:
	MOVE RATE (DESTINATIONZ, CLASSZ) TO RATE-PR.
Analyzing the move:

3-Dimension Tables in COBOL

Complex data sometimes requires sophistocated tables with multiple levels of dimensions within the table. Prior to COBOL 85, the three dimenision tables were the limit. COBOL 85 allows up to 7 dimensions of subscripting, we will stop with three!

Three dimension tables allow the user to access a table based on three subscripts and therefore makes a more complex table. This is an example of a three dimension table that could be used to establish phone rates. The calls are being originated from Boston and are being placed at a particular time of day, using either station to station or person to person, to a particular city.

  Day (1) Evening (2) Night (3)
TO Sta-to-Sta Pers-to-Pers Sta-to-Sta Pers-to-Pers Sta-to-Sta Pers-to-Pers
Fall River (1) 1.20 1.35 1.00 1.15   .85 1.00
New Bedford (2) 1.25 1.40 1.05 1.20   .90 1.05
Newport (3) 1.35 1.50 1.15 1.30 1.00 1.15
Providence(4) 1.40 1.55 1.20 1.35 1.05 1.20

The table could have been set up with any field chosen to be the major category and others the subcategories. This example uses time of day and then type of call within time of day and finally city being called within type of call. There is nothing special about this selection, it was totally arbitrary.

01  THREE-DIM-TABLE.
    05  DAY-RATES.
	10  DAY-S-S.
	    15  TO-FR  PIC 9V99 VALUE 1.20.
	    15  TO-NB  PIC 9V99 VALUE 1.25.
	    15  TO-NP  PIC 9V99 VALUE 1.35.
	    15  TO-PR  PIC 9V99 VALUE 1.40.
	10  DAY-P-P.
	    15  TO-FR  PIC 9V99 VALUE 1.35.
	    15  TO-NB  PIC 9V99 VALUE 1.40.
	    15  TO-NP  PIC 9V99 VALUE 1.50.
	    15  TO-PR  PIC 9V99 VALUE 1.55.
    05  EVENING-RATES.
	10  EVENING-S-S.
	    15  TO-FR  PIC 9V99 VALUE 1.00.
	    15  TO-NB  PIC 9V99 VALUE 1.05.
	    15  TO-NP  PIC 9V99 VALUE 1.15.
	    15  TO-PR  PIC 9V99 VALUE 1.20.
        10  EVENING-P-P.
	    15  TO-FR  PIC 9V99 VALUE 1.15.
	    15  TO-NB  PIC 9V99 VALUE 1.20.
	    15  TO-NP  PIC 9V99 VALUE 1.30.
	    15  TO-PR  PIC 9V99 VALUE 1.35.
    05  NIGHT-RATES.  
	10  NIGHT-S-S.  
	    15  TO-FR  PIC 9V99 VALUE 0.85.
	    15  TO-NB  PIC 9V99 VALUE 0.90.
	    15  TO-NP  PIC 9V99 VALUE 1.00.
            15  TO-PR  PIC 9V99 VALUE 1.05.
        10  NIGHT-P-P.  
	    15  TO-FR  PIC 9V99 VALUE 1.00.
            15  TO-NB  PIC 9V99 VALUE 1.05.
 	    15  TO-NP  PIC 9V99 VALUE 1.15.
	    15  TO-PR  PIC 9V99 VALUE 1.20.
01  RDF-THREE-DIM-TABLE REDEFINES THREE-DIM-TABLE.
    05  TIME-PERIODS OCCURS 3 TIMES.
        10  TYPE-CALLS OCCURS 2 TIMES.
	    15  RATE PIC 9V99 OCCURS 4 TIMES.
To use this table, there must be subscripts that tell the time of day, the type of call, and the destination city. The codes on the input that will be used as the subscripts are:

01   INPUT-RECORDS
     05  ...
     05  TIME-CODE    PIC 9.
     05  TYPE-CODE    PIC 9.
     05  PLACE-CODE   PIC 9.
Since the time of day is described on the 05 level, the first subscript must point to the correct 05 level for time of day. This means that TIME-CODE is the first subscript. Then the 10 level has entries for station to station and person to person, so the second subscript must point to the correct type. This means TYPE-CODE is the second subscript. Finally the 10 level is broken down into destinations that are shown on the 15 level. The third subscript must point to the correct 15 level. This means PLACE-CODE is the third subscript. If the table had been broken down differently, then the subscripting of the move statement would change to correspond. Assuming the goal is to move the RATE to a field on the printline, the MOVE statement would be:
MOVE RATE (TIME-CODE, TYPE-CODE, PLACE-CODE) TO RATE-PR.