Search code examples
mainframedfsort

Compare files with DFSORT , insert a string 'ADD' in front of new records


I have 2 work files old(F1) and new (F2), both of the same length. I should compare both the files record by record and for any new records in the new (F2) work file , I should insert 'ADD' in front of it in starting 3 positions and for rest of the records(matched) it should be spaces.

As of now I am able to copy the records which are in F2 but not in F1 using the below code:

//SYSIN DD *
 JOINKEYS FILE=F1,FIELDS=(1,79,A)
 JOINKEYS FILE=F2,FIELDS=(1,79,A)
 JOIN UNPAIRED,F2,ONLY
 SORT FIELDS=COPY
/*

but I need all the records from F2 with 'NEW' string in front of new records, can this be done in single step?


Solution

  • This seems to be what you want. I am not convinced you will want it shortly.

    All records on each file will be sorted based on, what I'm assuming is, their entire length. This means for the first run your output will be in a different sequence from the input.

    A "change" will look exactly the same as a NEW, if a change is possible.

    If you're OK with both of those, you should have said so in your question.

    //SYSIN DD *
    
     JOINKEYS FILE=F1,FIELDS=(1,79,A)
     JOINKEYS FILE=F2,FIELDS=(1,79,A)
    
     JOIN UNPAIRED,F2
    
     REFORMAT FIELDS=(?,F2:1,2,1,79)
    
     INREC IFTHEN=(WHEN=(1,1,CH,EQ,C'2'),
                     OVERLAY=(1:C'NEW')),
           IFTHEN=(WHEN=(NONE,
                     OVERLAY=(1:3X))
    
     SORT FIELDS=COPY
    

    The UNPAIRED,F2 will get you all matches, plus those from F2 (your NEW input) which don't match.

    The REFORMAT statement puts the join match-marker (the ?) in the first position, then puts two bytes of anything, then the entire data. The REFORMAT record will be 82 bytes.

    In INREC, the field sourced from the match-marker is tested so that NEW can be overlaid at the start of the record if required. Else, three blanks will be overlaid.

    There is a clearer way to express the same output:

    //SYSIN DD *
    
     JOINKEYS FILE=F1,FIELDS=(1,79,A)
     JOINKEYS FILE=F2,FIELDS=(1,79,A)
    
     JOIN UNPAIRED,F2
    
     REFORMAT FIELDS=(?,F2:1,79)
    
     INREC IFTHEN=(WHEN=(1,1,CH,EQ,C'2'),
                     BUILD=(C'NEW',2,79)),
           IFTHEN=(WHEN=(NONE,
                     BUILD=(3X,2,79)),
    
     SORT FIELDS=COPY
    

    This time BUILD is used, not OVERLAY.

    With better (any?) knowledge of your data, better solutions may be available.


    Even with information provided on another site but not here, there is not enough.

    //SYSIN DD *
     JOINKEYS FILE=F1,FIELDS=(1,79,A)
     JOINKEYS FILE=F2,FIELDS=(1,79,A)
     JOIN UNPAIRED,F2,ONLY
     SORT FIELDS=COPY
    /*
    

    We can guess that your file is 79, FB, but it needn't be.

    To only get the mismatches and put NEW at the front with your existing code, is easy:

    //SYSIN DD *
     JOINKEYS FILE=F1,FIELDS=(1,79,A)
     JOINKEYS FILE=F2,FIELDS=(1,79,A)
     JOIN UNPAIRED,F2,ONLY
     INREC BUILD=(C'NEW',1,79)
     SORT FIELDS=COPY
    

    You output is of course now 82 bytes per record.

    However, this presumes that you have (and can never have) no duplicates on you 79-byte key, and that your entire record is 79 bytes.

    It also assumes that you do not care about the order of the output file.

    Each JOINKEYS is SORTing its file, and then the data is presented to the matching process.

    Bear in mind that with a change, and this method of verifying (sort the whole record, compare the whole record), you will find it difficult to not output two records for a record which is logically the same. One will look like a Delete (from F1) and the other a NEW (on F2) whereas those taken together are just a Change.