Loops SAS中带有两个Set语句的嵌入式隐式循环

Loops SAS中带有两个Set语句的嵌入式隐式循环,loops,sas,Loops,Sas,我有下面的代码来跟踪特定的制造商优惠券发行。每期可以在赎回、过期和剩余字段中包含美元。我有一个发行表,给出所有发行和金额,赎回表是赎回或到期金额的会计。目标是通过在每个类别中放入适当的金额来跟踪每个发行的所有息票美元 该代码应该在ISSUE表中循环,并将赎回表中的匹配记录绑定到ISSUE表中的每条记录 /*create sample tables*/ data ISSUE; input Coupon_NBR $ AMOUNT REDEEMED EXPIRED RE

我有下面的代码来跟踪特定的制造商优惠券发行。每期可以在赎回、过期和剩余字段中包含美元。我有一个发行表,给出所有发行和金额,赎回表是赎回或到期金额的会计。目标是通过在每个类别中放入适当的金额来跟踪每个发行的所有息票美元

该代码应该在ISSUE表中循环,并将赎回表中的匹配记录绑定到ISSUE表中的每条记录

/*create sample tables*/
    data ISSUE; input
    Coupon_NBR $  AMOUNT  REDEEMED    EXPIRED    REMAINING; datalines;
    A           500     0           0           500
    A           500     0           0           500
    B           500     0           0           500
    B           500     0           0           500
    B           500     0           0           500
    B           1250    0           0           1250
    B           750     0           0           750
    C           500     0           0           500
    C           500     0           0           500
    C           500     0           0           500
    C           500     0           0           500
    C           500     0           0           500
    run;

data REDEMPTIONS; input
Redemp_coupon_NBR $ TRANS_AMOUNT     TYPE $16.; datalines;
A                      -150       REDEMPTION
A                      -350       REDEMPTION
A                      -200       EXPIRATION
B                      -300       REDEMPTION
B                      -200       EXPIRATION
B                     -1000       REDEMPTION
C                     -1500       REDEMPTION
C                      -500       EXPIRATION
run;

/*begin looping code*/
data Tracking;

    if _n_ = 1 then Link get_redemptions;
    set issue;
        if (remaining > 0) and (Coupon_NBR = Redemp_coupon_NBR) then do; 
            if trans_amount = 0 then                
               link get_redemptions;


            if trans_amount + remaining >=0 then do; 
               remaining = remaining + trans_amount;
               if type = 'EXPIRATION' then;         
                  expired = expired - trans_amount;

               if type = 'REDEMPTION' then;         
                  redeemed = redeemed - trans_amount;

               link get_redemptions;        
            end;                                    

            else do;                                 
               remaining = 0;
               if type = 'EXPIRATION' then do;         
                  expired = expired - trans_amount;
               end;                   
               else do;                            
                  redeemed = redeemed - trans_amount;      
                  trans_amount = trans_amount + remaining;
                  remaining = 0;
               end;                                 
            end; 
        end; 

        else do;
            link get_redemptions;
        end;                                        

    return;


    get_redemptions:
    set redemptions;
    return;

run;     
这是我得到的输出:

Coupon_NBR  AMOUNT  REDEEMED    EXPIRED REMAINING   redemp_coupon_nbr   trans_amount    type
A              500    150         150     350               A               -350    REDEMPTION
A              500    350         350     150               A               -200    EXPIRATION
B              500      0           0     500               B               -300    REDEMPTION
B              500    300         300     200               B               -200    EXPIRATION
B              500    200         200     300               B              -1000    REDEMPTION
B             1250   1000        1000     250               C              -1500    REDEMPTION
B              750      0           0     750               C               -500    EXPIRATION
在本例中,正确的输出为:

redemp_coupon_nbr   AMOUNT  REDEEMED    EXPIRED REMAINING
A                      500       500          0         0
A                      500         0        200       300
B                      500       300        200         0
B                      500       500          0         0
B                      500       500          0         0
B                     1250         0          0      1250
B                      750         0          0       750
C                      500       500          0         0
C                      500       500          0         0
C                      500       500          0         0
C                      500         0        500         0
C                      500         0          0       500
显然,我的结果离我想要的还很远。然而,我主要关心的是,当我希望它跟踪每个优惠券发行时,输出只有七行,这意味着我需要它有12行(发行表中每行一行)。我认为我的循环存在某种问题,具体表现在
Get retemptions
定义中。我已经调试了一段时间,但没有成功。

Jarom:

一个健壮的解决方案需要一种事务性分类账方法,以便正确处理以下备选方案:获取每张优惠券的多次赎回并跟踪超额,以及在获取额外赎回之前将超额应用于优惠券

下面的示例代码有许多put语句,因此您可以观察日志中的算法决策点。
余额
的目标是在每次交易对账时接近零(从上方或下方),并跟踪超出目标的任何部分

对于示例,这些变量名替换是针对您的数据进行的

  • 优惠券编号->G
  • 重新设计优惠券编号->XG
  • 运输量->装载量
您需要一个
链接
来获取赎回是正确的。
通过XG和
END=
添加
,进一步简化了分组处理

对REDUCTIONS end=变量的测试可防止过早停止数据步骤(如果在读取数据集最后一条记录后达到后续无条件集,则会发生这种情况)

下面是一些附加的示例数据

  • 非匹配赎回
  • B组有一个首次赎回,这是一个跨越两张优惠券的巨大超额
  • 无赎回的优惠券组
棘手的数据

data ISSUE; input
G $  AMOUNT;
A           500   
A           500    
B           500    
B           500    
B           500    
B           1250   
B           750    
B2          100
B2          200
C           500    
C           500    
C           500    
C           500    
C           500    
run;

data REDEMPTIONS; input
XG $ XAMOUNT     TYPE $16.; datalines;
!   -1000       REDEMPTION
A    -150       REDEMPTION
A    -350       REDEMPTION
A    -200       EXPIRATION
B   -1100       REDEMPTION   was -300
B    -200       EXPIRATION
B   -1000       REDEMPTION
C   -1500       REDEMPTION
C    -500       EXPIRATION
run;

如果没有任何
output
语句,则SAS将在数据步骤迭代结束时输出。听起来您的数据步骤只重复了7次。您只需要在准备就绪时显式输出观察值。大多数数据步骤在读取超过输入末尾时停止。在处理完
发行
中的所有记录之前,您不需要阅读超过
赎回结束时间的内容。您的输出不会反映整个情况,尤其是在第三个B,其中1000次赎回应用于500张优惠券,这意味着赎回余额为500(在以后的优惠券中使用)。我认为,一般来说,你不希望允许赎回超过票面金额。你将需要一个相当数量的脚手架,以允许旋转超过赎回或耦合。“脚手架”将是当前余额、赎回金额、到期金额、赎回余额和到期余额的变量谢谢你的回答。我发现我过分简化了这个过程。你的解决方案有效。非常感谢你!
data ISSUE; input
G $  AMOUNT;
A           500   
A           500    
B           500    
B           500    
B           500    
B           1250   
B           750    
B2          100
B2          200
C           500    
C           500    
C           500    
C           500    
C           500    
run;

data REDEMPTIONS; input
XG $ XAMOUNT     TYPE $16.; datalines;
!   -1000       REDEMPTION
A    -150       REDEMPTION
A    -350       REDEMPTION
A    -200       EXPIRATION
B   -1100       REDEMPTION   was -300
B    -200       EXPIRATION
B   -1000       REDEMPTION
C   -1500       REDEMPTION
C    -500       EXPIRATION
run;