MVSFORUMS.com Forum Index MVSFORUMS.com
A Community of and for MVS Professionals
 
 FAQFAQ   SearchSearch   Quick Manuals   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Copy Last 50 records from a file
Goto page 1, 2  Next
 
Post new topic   Reply to topic   printer-friendly view    MVSFORUMS.com Forum Index -> Job Control Language(JCL)
View previous topic :: View next topic  
Author Message
keshav
Beginner


Joined: 08 Dec 2004
Posts: 3
Topics: 2

PostPosted: Wed Dec 08, 2004 3:08 am    Post subject: Copy Last 50 records from a file Reply with quote

let us take a file that contain some number of records and the exact number of records are not known and if i want to copy the last 50 records how can we do it

Note: Title edited by the moderator and moved to the JCL forum
Back to top
View user's profile Send private message
Phantom
Data Mgmt Moderator
Data Mgmt Moderator


Joined: 07 Jan 2003
Posts: 1056
Topics: 91
Location: The Blue Planet

PostPosted: Wed Dec 08, 2004 5:04 am    Post subject: Reply with quote

Keshav,

Please follow the Forum rules. "Please provide a Relevant Title for your question". JCL has no meaning / relevance to your question.

Ok....There are couple of ways to do this, especially using SORT.

Solution 1: Sort (Pretty old version of Syncsort that does not support REMOVECC Parm). If your shop has DFSORT replace SYNCTOOL by ICETOOL and run ur code.

Code:

//R010     EXEC PGM=SYNCTOOL         
//TOOLMSG  DD  SYSOUT=*               
//DFSMSG   DD  SYSOUT=*               
//INPUT    DD  *                     
ONE                                   
TWO                                   
THREE                                 
FOUR                                 
FIVE                                 
SIX                                   
SEVEN                                 
EIGHT                                 
NINE                                 
TEN                                   
ELEVEN                               
TWELVE                               
/*                                   
//TEMP     DD  DSN=&&T1,DISP=(,PASS) 
//CTL3CNTL DD  DSN=&&T2,DISP=(,PASS) 
//OUTPUT   DD  SYSOUT=*               
//TOOLIN   DD  *                     
  COPY FROM(INPUT) TO(TEMP)     USING(CTL1)                 
  COPY FROM(TEMP)  TO(CTL3CNTL) USING(CTL2)                 
  COPY FROM(INPUT) TO(OUTPUT)   USING(CTL3)                 
/*                                                           
//CTL1CNTL DD  *                                             
  OUTFIL TRAILER1=(COUNT),                                   
         NODETAIL                                           
/*                                                           
//CTL2CNTL DD  *                                             
  INREC FIELDS=(C' SKIPREC=',2,8,FS,SUB,+5,EDIT=(TTTTTTTT)) 
/*                                                           


Brief Description:
The OUTFIL TRAILER1=(COUNT) will give the count of records in the input file. NODETAIL parm will suppress the actual records from being written to the output. After getting the count, subtract 5 (just for example, you need to use 50 as per ur requirement) from the count & generate a small Sort control card which uses SKIPREC=n to skip first (count - 50) records.

Solution 2: If you have DFSORT or a bit latest version of Syncsort which supports REMOVECC parm of TRAILER1. Use this.

Code:

//R010     EXEC PGM=SYNCTOOL         
//TOOLMSG  DD  SYSOUT=*               
//DFSMSG   DD  SYSOUT=*               
//INPUT    DD  *                     
ONE                                   
TWO                                   
THREE                                 
FOUR                                 
FIVE                                 
SIX                                   
SEVEN                                 
EIGHT                                 
NINE                                 
TEN                                   
ELEVEN                               
TWELVE                               
/*                                   
//CTL2CNTL DD  DSN=&&T2,DISP=(,PASS) 
//OUTPUT   DD  SYSOUT=*               
//TOOLIN   DD  *                     
  COPY FROM(INPUT) TO(CTL2CNTL)  USING(CTL1)                 
  COPY FROM(INPUT) TO(OUTPUT)     USING(CTL2)                 
/*                                                           
//CTL1CNTL DD  * 
  INREC FIELDS=(1,80,
            SEQNUM,8,ZD)               
  OUTREC FIELDS=(c'  SKIPREC=',81,8,ZD,SUB,+5,EDIT=(TTTTTTTT),80:X)
  OUTFIL TRAILER1=(1,80),REMOVECC,NODETAIL                                           
/*                                                                                                             


Brief Description:
Assuming your input file is of length 80 & RECFM=FB, I included 8 digit SEQNUM (Sequence Number) at the end of layout. Then in OUTREC the record the sequence numbers are subtracted from 5 (You need to use 50). Finally OUTFIL TRAILER1 writes only the last record which contains the actual value (record count - 5) i.e., seqnum of last record (which is same as record count) - 5.

When u use OUTFIL TRAILER the output is generated as FBA and an Ansi char is inserted in col 1. REMOVECC is used to remove that.

Hope this helps,

Thanks,
Phantom
Back to top
View user's profile Send private message
rajamohamed
Beginner


Joined: 08 Dec 2004
Posts: 2
Topics: 0

PostPosted: Wed Dec 08, 2004 5:43 am    Post subject: Reply with quote

Is the same is possible using other than ICETOOL/SYNCTOOL untilities
_________________
Best Regards
Rajamohamed
Back to top
View user's profile Send private message
kolusu
Site Admin
Site Admin


Joined: 26 Nov 2002
Posts: 12375
Topics: 75
Location: San Jose

PostPosted: Wed Dec 08, 2004 5:56 am    Post subject: Reply with quote

rajamohamed,

You can use Fileaid's COPYBACK feature to read the records backwards. You can control the no: of records written using the OUT feature.

Code:

//STEP0100 EXEC PGM=FILEAID                                           
//SYSPRINT DD SYSOUT=*                                               
//DD01     DD DSN=YOUR INPUT DATASET,
//            DISP=SHR
//DD01O    DD DSN=YOUR LAST 50 RECS IN REVERSE,
//            DISP=(NEW,CATLG,DELETE),
//            UNIT=SYSDA,
//            SPACE=(CYL,(X,Y),RLSE)
//SYSIN    DD  *
$$DD01 COPYBACK OUT=50                                                 
/*                                                                   


The above JCL will produce an output file of the last 50 records in the reverse order.i.e the last record will be the first record and so on.

If you want the orginal order then you simply need another step to reverse the file.

Code:

//STEP0200 EXEC PGM=FILEAID                                           
//SYSPRINT DD SYSOUT=*                                               
//DD01     DD DSN=OUTPUT OF STEP0100 DATASET,
//            DISP=SHR
//DD01O    DD DSN=YOUR LAST 50 RECS,
//            DISP=(NEW,CATLG,DELETE),
//            UNIT=SYSDA,
//            SPACE=(CYL,(X,Y),RLSE)
//SYSIN    DD  *
$$DD01 COPYBACK OUT=50                                                 
/*                                                                   


Hope this helps...

Cheers

Kolusu
_________________
Kolusu
www.linkedin.com/in/kolusu
Back to top
View user's profile Send private message Send e-mail Visit poster's website
rajamohamed
Beginner


Joined: 08 Dec 2004
Posts: 2
Topics: 0

PostPosted: Wed Dec 08, 2004 6:35 am    Post subject: Reply with quote

FileAid's - COPYBACK newthing I have learnt , thaxs kolusu
_________________
Best Regards
Rajamohamed
Back to top
View user's profile Send private message
Phantom
Data Mgmt Moderator
Data Mgmt Moderator


Joined: 07 Jan 2003
Posts: 1056
Topics: 91
Location: The Blue Planet

PostPosted: Thu Dec 09, 2004 1:54 am    Post subject: Reply with quote

Keshav,

Here is one another solution that will work with any version of Syncsort/Dfsort. Credit goes to my friend who came up with this solution.

Code:

//STEP0010 EXEC PGM=SYNCTOOL       
//SYSOUT   DD SYSOUT=*             
//SYSPRINT DD SYSOUT=*             
//TOOLMSG  DD SYSOUT=*             
//DFSMSG   DD SYSOUT=*             
//IN       DD *                   
1                                 
2                                 
3                                 
4                                 
5                                 
6                                 
7                                 
8                                 
9                                                               
0                                                               
11                                                               
12                                                               
/*                                                               
//CTL2CNTL DD DSN=&&C2,UNIT=SYSDA,SPACE=(TRK,(1,1)),DISP=(,PASS)
//OUT      DD SYSOUT=*                                           
//TOOLIN   DD *                                                 
  SORT FROM(IN) TO(CTL2CNTL) USING(CTL1)                         
  COPY FROM(IN) TO(OUT) USING(CTL2)                             
/*                                                               
//CTL1CNTL DD *                                                 
 INREC FIELDS=(SEQNUM,8,ZD)                                     
 SORT FIELDS=(1,8,ZD,D)                                         
 OUTFIL OUTREC=(C' SKIPREC=',1,8,ZD,SUB,+5,M11,LENGTH=8),ENDREC=1
                                                                 
/*                                                               


Brief Description:
1. Using INREC generate 8 digit sequence numbers. (Note: Input Data is not copied here)
2. Sort the records in descending order of Sequence no.
3. Pick up the first record in descending order (which is actually the last record of the actual file) and Subtract the required no. of records (50 as per your requirement) from the sequence no.
4. Generate a dynamic sort control card which will have SKIPREC=n (where n is the output of the subtraction).

Thanks,
Phantom
Back to top
View user's profile Send private message
kolusu
Site Admin
Site Admin


Joined: 26 Nov 2002
Posts: 12375
Topics: 75
Location: San Jose

PostPosted: Thu Dec 09, 2004 6:30 am    Post subject: Reply with quote

Phantom,

Here is a slight modification of your job. Since you are already sorting, you don't need to generate the CTL2 control card once again. In the first pass itself write out the last 50 records using the endrec feature. Now you have the records in reverse order. All you need is another sort on seqnum ascending so that the original order is retained. You also don't need the sysout and sysprint datasets.

Code:

//STEP0010 EXEC PGM=SYNCTOOL       
//TOOLMSG  DD SYSOUT=*             
//DFSMSG   DD SYSOUT=*             
//IN       DD *                   
1                                 
2                                 
3                                 
4                                 
5                                 
6                                 
7                                 
8                                 
9                                                               
0                                                               
11                                                               
12                                                               
/*                                                               
//T1       DD DSN=&&T1,UNIT=SYSDA,SPACE=(CYL,(X,Y),RLSE),DISP=(,PASS)
//OUT      DD SYSOUT=*
//TOOLIN   DD *
  SORT FROM(IN) USING(CTL1)
  SORT FROM(T1) USING(CTL2)
/*
//CTL1CNTL DD * 
  INREC FIELDS=(1,80,SEQNUM,8,ZD)
  SORT FIELDS=(81,8,ZD,D)
  OUTFIL FNAMES=T1,ENDREC=50
/*
//CTL2CNTL DD * 
  SORT FIELDS=(81,8,ZD,A)
  OUTFIL FNAMES=OUT,OUTREC=(1,80)
/*   


Hope this helps...

Cheers

Kolusu
_________________
Kolusu
www.linkedin.com/in/kolusu
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Phantom
Data Mgmt Moderator
Data Mgmt Moderator


Joined: 07 Jan 2003
Posts: 1056
Topics: 91
Location: The Blue Planet

PostPosted: Thu Dec 09, 2004 6:48 am    Post subject: Reply with quote

Kolusu,

Now we have one more solution to accomplish the same task !!!.

I did not see the SYSPRINT & SYSOUT in my post. I just copied & pasted my friend's solution!. Thanks a lot for pointing it out.

Btw, Actually I advised my friend to minimize the no. of SORTs as much as possible, b'cas COPY is much faster than the SORT operation. It does not matter much for smaller files but in my perception, we should always think of efficiency so that we can get a better solution (if not the best). Wink I'm just following ur foot steps Kolusu.

Thanks,
Phantom
Back to top
View user's profile Send private message
keshav
Beginner


Joined: 08 Dec 2004
Posts: 3
Topics: 2

PostPosted: Fri Dec 24, 2004 3:52 am    Post subject: Reply with quote

thank you very much for giving the solution
Back to top
View user's profile Send private message
Frank Yaeger
Sort Forum Moderator
Sort Forum Moderator


Joined: 02 Dec 2002
Posts: 1618
Topics: 31
Location: San Jose

PostPosted: Fri Dec 24, 2004 11:47 am    Post subject: Reply with quote

With z/OS DFSORT V1R5 PTF UQ95214 or DFSORT R14 PTF UQ95213 (Dec, 2004), you can now use COUNT-n=(edit) in the TRAILERx parameter to do this more easily with a DFSORT/ICETOOL job like this:

Code:

//S1     EXEC PGM=ICETOOL
//TOOLMSG  DD  SYSOUT=*
//DFSMSG   DD  SYSOUT=*
//INPUT    DD  DSN=...  input file
//CTL2CNTL DD  DSN=&&T1,UNIT=SYSDA,SPACE=(TRK,(1,1)),DISP=(,PASS)
//OUTPUT   DD  DSN=...  output file
//TOOLIN   DD  *
  COPY FROM(INPUT) USING(CTL1)
  COPY FROM(INPUT) TO(OUTPUT) USING(CTL2)
/*
//CTL1CNTL DD  *
  OUTFIL FNAMES=CTL2CNTL,REMOVECC,NODETAIL,
    OUTREC=(80X),
    TRAILER1=(' OPTION SKIPREC=',COUNT-5=(TO=ZD,LENGTH=8))
/*


For complete information on all of the new DFSORT and ICETOOL functions available with these DFSORT PTFs, see:

www.ibm.com/servers/storage/support/software/sort/mvs/pdug/

If you don't have the new PTFs, you can use a DFSORT/ICETOOL job like this:

Code:

//S2     EXEC PGM=ICETOOL
//TOOLMSG  DD  SYSOUT=*
//DFSMSG   DD  SYSOUT=*
//INPUT    DD  DSN=... input file
//CTL2CNTL DD  DSN=&&T2,UNIT=SYSDA,SPACE=(TRK,(1,1)),DISP=(,PASS)
//OUTPUT   DD  DSN=...  output file
//TOOLIN   DD  *
  COPY FROM(INPUT) USING(CTL1)
  COPY FROM(INPUT) TO(OUTPUT)     USING(CTL2)
/*
//CTL1CNTL DD  *
  INREC FIELDS=(1,80,
            SEQNUM,8,ZD)
  OUTREC FIELDS=(C'  OPTION SKIPREC=',
    81,8,ZD,SUB,+5,M11,LENGTH=8,80:X)
  OUTFIL FNAMES=CTL2CNTL,TRAILER1=(1,80),REMOVECC,NODETAIL
/*


This is a version of the job phantom showed earlier with some needed corrections (' OPTION SKIPREC=' and FNAMES=CTL2CNTL).
_________________
Frank Yaeger - DFSORT Development Team (IBM)
Specialties: JOINKEYS, FINDREP, WHEN=GROUP, ICETOOL, Symbols, Migration
DFSORT is on the Web at:
www.ibm.com/storage/dfsort
Back to top
View user's profile Send private message Send e-mail Visit poster's website
gharisankar
Beginner


Joined: 10 Jul 2004
Posts: 19
Topics: 3
Location: C/O Platform - Mainframe

PostPosted: Fri Dec 24, 2004 2:26 pm    Post subject: Reply with quote

Hi ,

Would you please describe the details about the control card ?

"INREC FIELDS=(C' SKIPREC=',2,8,FS,SUB,+5,EDIT=(TTTTTTTT)) "

This is used to design the conrol card, but I am bit confused about the parameters which was given.

TTTTTTTT - The no: of records (ex : 00000004)
FS - ??? ( This is edit pattern, but want to more about this)
2,8 - The control card starting position ( Is it?)

Thanks in Advance !!!
_________________
Regards
Hari Smile
Back to top
View user's profile Send private message
Frank Yaeger
Sort Forum Moderator
Sort Forum Moderator


Joined: 02 Dec 2002
Posts: 1618
Topics: 31
Location: San Jose

PostPosted: Fri Dec 24, 2004 5:30 pm    Post subject: Reply with quote

Hari,

You didn't say, but I guess your question is directed to Phantom since you're asking about the INREC statement in his post - right?
_________________
Frank Yaeger - DFSORT Development Team (IBM)
Specialties: JOINKEYS, FINDREP, WHEN=GROUP, ICETOOL, Symbols, Migration
DFSORT is on the Web at:
www.ibm.com/storage/dfsort
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Phantom
Data Mgmt Moderator
Data Mgmt Moderator


Joined: 07 Jan 2003
Posts: 1056
Topics: 91
Location: The Blue Planet

PostPosted: Sat Dec 25, 2004 5:59 am    Post subject: Reply with quote

Hari,

Here is the explanation of my code:
Code:

//TOOLIN   DD  *                     
  COPY FROM(INPUT) TO(TEMP)     USING(CTL1)                 
  COPY FROM(TEMP)  TO(CTL3CNTL) USING(CTL2)                 
  COPY FROM(INPUT) TO(OUTPUT)   USING(CTL3)                 
/*                                                           
//CTL1CNTL DD  *                                             
  OUTFIL TRAILER1=(COUNT),                                   
         NODETAIL                                           
/*                                                           
//CTL2CNTL DD  *                                             
  INREC FIELDS=(C' SKIPREC=',2,8,FS,SUB,+5,EDIT=(TTTTTTTT)) 
/*                                       


1. COPY FROM(INPUT) TO(TEMP) USING(CTL1)
The sort control card CTL1 uses the OUTFIL TRAILER feature to get the record count of input file. NODETAIL parm will suppress the input records from being written to the output file. So the output file will contain only 1 record with the record COUNT. Since we have a old version of SYNCSORT, REMOVECC parm of TRAILER is not supported here. Hence the output file is created as FBA instead of FB as shown below.

Assuming we have 12 records in the input file, the temp. file is created as shown below. The character '1' in col 1 is the print control character (for FBA file). The COUNT is displayed as ZZZZZZZ9 - 8 digit count with leading zeroes suppressed.
Code:

----+----1----+----2
1      12


2. COPY FROM(TEMP) TO(CTL3CNTL) USING(CTL2)
Now, the control card CTL2 takes this COUNT from positions 2 thru' 9 and subtracts '5' from it. By default the arithmetic operations like ADD,SUB,DIV,MUL will write the output in 15 digit ZD format. I then applied the EDIT pattern (TTTTTTTT - same as COBOL 99999999) to truncate the 15 digit result to 8 digits with leading zeroes RETAINED.

The next question will be about 'FS'. When ever we do an arithmetic operation, we need to inform sort about the data type of source fields. Here the source field is the count in positions 2 thru' 9. FS is used to indicate sort that the source field is numeric EDITED with leading zeroes suppressed.

Hope my explanation was clear. Please let me know if you have any questions,

Thanks,
Phantom
Back to top
View user's profile Send private message
gharisankar
Beginner


Joined: 10 Jul 2004
Posts: 19
Topics: 3
Location: C/O Platform - Mainframe

PostPosted: Sat Dec 25, 2004 10:14 pm    Post subject: Reply with quote

MERRY XMAS !!! Laughing
Thanks Phantom. ( navin)..
its awesome !
_________________
Regards
Hari Smile
Back to top
View user's profile Send private message
Frank Yaeger
Sort Forum Moderator
Sort Forum Moderator


Joined: 02 Dec 2002
Posts: 1618
Topics: 31
Location: San Jose

PostPosted: Thu Aug 07, 2008 4:31 pm    Post subject: Reply with quote

With z/OS DFSORT V1R5 PTF UK90013 (July, 2008), you can now use SUBSET to do this kind of thing quite easily like this:

Code:

//S1   EXEC  PGM=ICETOOL
//TOOLMSG   DD  SYSOUT=*
//DFSMSG    DD  SYSOUT=*
//IN DD DSN=...  input file
//OUT DD DSN=...  output file
//TOOLIN DD *
SUBSET FROM(IN) TO(OUT) KEEP INPUT LAST(50)
/*


For complete details on the new SUBSET function and the other new functions available with PTF UK90013, see:

www.ibm.com/systems/support/storage/software/sort/mvs/ugpf/
_________________
Frank Yaeger - DFSORT Development Team (IBM)
Specialties: JOINKEYS, FINDREP, WHEN=GROUP, ICETOOL, Symbols, Migration
DFSORT is on the Web at:
www.ibm.com/storage/dfsort
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic   printer-friendly view    MVSFORUMS.com Forum Index -> Job Control Language(JCL) All times are GMT - 5 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


MVSFORUMS
Powered by phpBB © 2001, 2005 phpBB Group