主机 JCL 记录转置使用 SORT

4
我想使用SORT(snycsort或DFSORT)将记录转置为列,这应该可扩展到任意数量的记录。这种转置是否可能?
DE001XYX   A 
CD100000 B
CD200000 C
DE001KKK A
CD100000 B
DE003ZZZ A
DE001XYX A
CD100000 B
CD200000 C
DE001KKK A
CD100000 B
........

转置

DE001XYX   CD100000   CD200000   
DE001KKK   CD100000   
DE003ZZZ   
DE001XYX   CD100000   CD200000   
DE001KKK   CD100000   
.....

请告诉我们您正在使用哪个排序产品:DFSORT、Syncsort等,并将这些标签添加到您的问题中。 - cschneid
它如何扩展到任意数量的记录?您只有26个字母表中的字母,并且记录长度有最大值。输出顺序是否重要(因为数据至少需要排序一次)? - Bill Woodger
只有三个键,分别是A、B、C。A对应以DE开头的记录,B对应以CD1开头的记录,C对应以CD2开头的记录。每个DE记录都与其下面的记录即CD1和CD2记录相关联。 - Kevin
如果你仍在解决这个问题,为什么不使用REXX呢? - paulywill
1个回答

2
这是一个我收藏了很久并且渴望自己解决的问题。经过一些研究和尝试,我终于想出了一个解决方案。

更新:下面给出了改进的方法。它在一次遍历中解决了问题,而最初的方法需要三次遍历。

改进的方法: 不需要三次遍历。

***************************** Top of Data ******************************
//JOBNAME JOB ('ACCOUNT INFORMATION'),'TRANSPOSE',                      
//     CLASS=2,MSGCLASS=H,NOTIFY=&SYSUID                                
//STEP1   EXEC PGM=SORT                                                 
//SORTIN  DD *                                                          
DE001XYX   A                                                            
CD100000   B                                                            
CD200000   C                                                            
DE001KKK   A                                                            
CD100000   B                                                            
DE003ZZZ   A                                                            
DE001XYX   A                                                            
CD100000   B                                                            
CD200000   C                                                            
DE001KKK   A                                                            
CD100000   B                                                            
//SORTOUT DD SYSOUT=*                                                   
//SYSOUT  DD SYSOUT=*                                                   
//SYSIN   DD *                                                          
 SORT FIELDS=(30,1,CH,A)                                                
 INREC IFTHEN=(WHEN=GROUP,BEGIN=(12,1,CH,EQ,C'A'),                      
              END=(12,1,CH,EQ,C'C'),PUSH=(14:ID=1)),                    
       IFTHEN=(WHEN=(12,1,CH,EQ,C'A'),BUILD=(1:1,8,19Z,28:12,1,         
              30:14,1)),                                                
       IFTHEN=(WHEN=(12,1,CH,EQ,C'B'),                                  
              BUILD=(1:9Z,10:1,8,18:10Z,28:12,1,30:14,1)),              
       IFTHEN=(WHEN=(12,1,CH,EQ,C'C'),                                  
              BUILD=(1:18Z,19:1,8,28:12,1,30:14,1))                     
 SUM FIELDS=(1,8,10,8,19,8),FORMAT=BI                                   
 OUTREC FIELDS=(1:1,8,9:X,10:10,8,18:X,19:19,8)                         
**************************** Bottom of Data ****************************

结果与OP在问题中显示的输出相同。


初始方法:

步骤1: 我使用了WHEN=GROUPBEGINENDPUSH参数。

//JOBNAME JOB ('ACCOUNT NAME'),'TRANSPOSE',          
//     CLASS=2,MSGCLASS=H,NOTIFY=&SYSUID             
//STEP1   EXEC PGM=SORT                              
//SORTIN  DD *                                       
DE001XYX   A                                         
CD100000   B                                         
CD200000   C                                         
DE001KKK   A                                         
CD100000   B                                         
DE003ZZZ   A                                         
DE001XYX   A                                         
CD100000   B                                         
CD200000   C                                         
DE001KKK   A                                         
CD100000   B                                         
//SORTOUT DD SYSOUT=*                                
//SYSOUT  DD SYSOUT=*                                
//SYSIN   DD *                                       
 SORT FIELDS=COPY                                    
 OUTREC IFTHEN=(WHEN=GROUP,BEGIN=(12,1,CH,EQ,C'A'),  
               END=(12,1,CH,EQ,C'C'),PUSH=(14:ID=1))

PUSH =(14:ID = 1) 意味着位置14的1是一个每个组都增加的标识符。无论之前的组是否以C终止,每个A都表示一个新组。当开始一个新组时,标识符将+1。

注意:由于我们只允许为ID使用一个字符,当ID计数器达到10时,'0'将出现在第14位置。您还可以为ID分配多个字节。

步骤1的输出:

********************************* TOP OF DATA **********************************
DE001XYX   A 1                                                                  
CD100000   B 1                                                                  
CD200000   C 1                                                                  
DE001KKK   A 2                                                                  
CD100000   B 2                                                                  
DE003ZZZ   A 3                                                                  
DE001XYX   A 4                                                                  
CD100000   B 4                                                                  
CD200000   C 4                                                                  
DE001KKK   A 5                                                                  
CD100000   B 5                                                                  
******************************** BOTTOM OF DATA ********************************

步骤2:获取步骤1的输出。根据三个键A、B和C,修改DE、CD1和CD2记录的位置。

//JOBNAME JOB ('ACCOUNT NAME'),'TRANSPOSE',                     
//     CLASS=2,MSGCLASS=H,NOTIFY=&SYSUID                        
//STEP1   EXEC PGM=SORT                                         
//SORTIN  DD *                                                  
DE001XYX   A 1                                                  
CD100000   B 1                                                  
CD200000   C 1                                                  
DE001KKK   A 2                                                  
CD100000   B 2                                                  
DE003ZZZ   A 3                                                  
DE001XYX   A 4                                                  
CD100000   B 4                                                  
CD200000   C 4                                                  
DE001KKK   A 5                                                  
CD100000   B 5                                                  
//SORTOUT DD SYSOUT=*                                           
//SYSOUT  DD SYSOUT=*                                           
//SYSIN   DD *                                                  
 SORT FIELDS=COPY                                               
 OUTREC IFTHEN=(WHEN=(12,1,CH,EQ,C'A'),BUILD=(1:1,8,19Z,28:12,1,
               30:14,1)),                                       
        IFTHEN=(WHEN=(12,1,CH,EQ,C'B'),                         
               BUILD=(1:9Z,10:1,8,18:10Z,28:12,1,30:14,1)),     
        IFTHEN=(WHEN=(12,1,CH,EQ,C'C'),                         
               BUILD=(1:18Z,19:1,8,28:12,1,30:14,1))            
/*      

注意:二进制零被插入其中,作为占位符,以便在第三步中填充数据。

第二步的输出:

********************************* TOP OF DATA **********************************
DE001XYX                   A 1                                                  
         CD100000          B 1                                                  
                  CD200000 C 1                                                  
DE001KKK                   A 2                                                  
         CD100000          B 2                                                  
DE003ZZZ                   A 3                                                  
DE001XYX                   A 4                                                  
         CD100000          B 4                                                  
                  CD200000 C 4                                                  
DE001KKK                   A 5                                                  
         CD100000          B 5                                                  
******************************** BOTTOM OF DATA ********************************

开启十六进制模式,您将能够看到二进制零(X'00)。

***************************** Top of Data ******************************
DE001XYX                   A 1                                          
CCFFFEEE0000000000000000000C4F444444444444444444444444444444444444444444
450017870000000000000000000101000000000000000000000000000000000000000000
----------------------------------------------------------------------- 
         CD100000          B 1                                          
000000000CCFFFFFF0000000000C4F444444444444444444444444444444444444444444
000000000341000000000000000201000000000000000000000000000000000000000000
----------------------------------------------------------------------- 
                  CD200000 C 1                                          
000000000000000000CCFFFFFF4C4F444444444444444444444444444444444444444444
000000000000000000342000000301000000000000000000000000000000000000000000
----------------------------------------------------------------------- 
DE001KKK                   A 2                                          
CCFFFDDD0000000000000000000C4F444444444444444444444444444444444444444444
450012220000000000000000000102000000000000000000000000000000000000000000
----------------------------------------------------------------------- 
         CD100000          B 2                                          
000000000CCFFFFFF0000000000C4F444444444444444444444444444444444444444444
000000000341000000000000000202000000000000000000000000000000000000000000
----------------------------------------------------------------------- 
DE003ZZZ                   A 3                                          
CCFFFEEE0000000000000000000C4F444444444444444444444444444444444444444444
450039990000000000000000000103000000000000000000000000000000000000000000
----------------------------------------------------------------------- 
DE001XYX                   A 4                                          
CCFFFEEE0000000000000000000C4F444444444444444444444444444444444444444444
450017870000000000000000000104000000000000000000000000000000000000000000
----------------------------------------------------------------------- 
         CD100000          B 4                                          
000000000CCFFFFFF0000000000C4F444444444444444444444444444444444444444444
000000000341000000000000000204000000000000000000000000000000000000000000
----------------------------------------------------------------------- 
                  CD200000 C 4                                          
000000000000000000CCFFFFFF4C4F444444444444444444444444444444444444444444
000000000000000000342000000304000000000000000000000000000000000000000000
DE001KKK                   A 5                                          
CCFFFDDD0000000000000000000C4F444444444444444444444444444444444444444444
450012220000000000000000000105000000000000000000000000000000000000000000
----------------------------------------------------------------------- 
         CD100000          B 5                                          
000000000CCFFFFFF0000000000C4F444444444444444444444444444444444444444444
000000000341000000000000000205000000000000000000000000000000000000000000
----------------------------------------------------------------------- 
**************************** Bottom of Data ****************************

步骤3:使用第2步的输出作为输入,使用SUM FIELDS将组的DE、CD1和CD2记录组合起来,在第30个位置上使用ID字段进行SORT FIELDS

//JOBNAME JOB ('ACCOUNT NAME'),'TRANSPOSE',                     
//     CLASS=2,MSGCLASS=H,NOTIFY=&SYSUID                        
//STEP1   EXEC PGM=SORT                                         
//SORTIN  DD *                                                  
DE001XYX                   A 1                                                  
         CD100000          B 1                                                  
                  CD200000 C 1                                                  
DE001KKK                   A 2                                                  
         CD100000          B 2                                                  
DE003ZZZ                   A 3                                                  
DE001XYX                   A 4                                                  
         CD100000          B 4                                                  
                  CD200000 C 4                                                  
DE001KKK                   A 5                                                  
         CD100000          B 5                                                  
//SORTOUT DD SYSOUT=*                                           
//SYSOUT  DD SYSOUT=*                                           
//SYSIN   DD *
  SORT FIELDS=(30,1,CH,A)                       
  SUM FIELDS=(1,8,10,8,19,8),FORMAT=BI          
  OUTREC FIELDS=(1:1,8,9:X,10:10,8,18:X,19:19,8)
/* 

使用 OUTREC FIELDS=(1:1,8,9:X,10:10,8,18:X,19:19,8),将 DE、CD1 和 CD2 字段之间的二进制零替换为空格。

第三步的输出:这是你需要的!

***************************** Top of Data ******************************
DE001XYX CD100000 CD200000                                              
DE001KKK CD100000                                                       
DE003ZZZ                                                                
DE001XYX CD100000 CD200000                                              
DE001KKK CD100000                                                       
**************************** Bottom of Data ****************************

关于二进制零的SUM FIELDS更多细节:

二进制加法运算是在两个位模式上进行的。让我们考虑以下记录(Hex模式已打开,因为我想展示如何对Hex值执行二进制加法)。

****** ********
000001 DE001XYX
       CCFFFEEE
       45001787
---------------
000002         
       00000000
       00000000

第一个字节的十六进制值 X'C4'正被加到第二个记录的第一个字节的二进制零上。

 C4
+00
 --
 C4

X'C4'表示EBCDIC编码中的字母'D'

如果我们将第一个字节中的二进制零更改为二进制一(X'01'),则结果会有所不同。

 C4
+01
 --
 C5

X'C5'代表EBCDIC中的字母'E'。

使用二进制零,我们可以对包含字母数字数据项(EBCDIC字符a-z、A-Z、0-9)的数据执行SUM FIELDS操作,将它们分组到一个单独的记录中。



1
非常感谢您的努力。实际上,我已经发布了这个问题并忘记了。我已经通过JCL和BTEQ Teradata查询解决了这个问题。 - Kevin
嗨@user2959433,很高兴听到你已经找到了解决方案。由于Syncsort被标记在问题中,我考虑使用它来找到解决方案。这是相当具有挑战性的,并揭示了新的可能性。 - Srinivasan JV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接