楼主: zengweixiong
3406 8

data步与PROC步的交互问题call execute [推广有奖]

  • 0关注
  • 1粉丝

VIP

已卖:61份资源

大专生

26%

还不是VIP/贵宾

-

威望
0
论坛币
605 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
362 点
帖子
26
精华
0
在线时间
21 小时
注册时间
2006-4-26
最后登录
2017-6-11

楼主
zengweixiong 发表于 2012-8-21 17:34:50 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
使用的SAS版本是 9.13

我有 一张描述信用卡信息的  卡表(Cards),有  卡号、信用额度、余额 等字段
现在模拟交易的交易:
1、随机取一张卡
2、随机产生一个消费金额
3、判断消费额度是否超过信用卡的余额
4.1、如果未超过,则 将 原来的余额减去 这次的消费金额  为新的 余额
4.2、如果超过,则此次不消费,只对此张信用卡还款。
5、循环上面的过程,直至完成需要的次数。

我写的代码见后面。

现在存在的问题是,call execute 是在我的DATA步骤结束后,再去执行相关的MACRO。
请问在我如何在尽量小改小的前提下,实现我的目的。

%macro updatetable(Cardnum=,AfterUpdateBal=);
proc sql;
  update Cards
     set Bal=&AfterUpdateBal.
         where Card_num="&Cardnum.";
quit;
%mend;

%macro repay(Cardnum=);
proc sql;
  update Cards
     set Bal=LIMIT_AMT
         where Card_num="&Cardnum.";
quit;
%mend;


data trans;
  do i=1 to 100;
    mycardpoint=CEIL(RANUNI(0)*mycardnobs);
          set Cards POINT=mycardpoint nobs=mycardnobs;  /*随机取一张卡*/
    Tx_Amt=1000*rand('uniform');                  /*随机产生一个消费金额*/

          if(Bal>=Tx_Amt) then do;                      /*如果余额为够此次消费,则更新余额*/
            Bal=Bal-Tx_Amt;                             /*更新  “余额” */
      call execute('%updatetable(Cardnum='||Card_num||',AfterUpdateBal='||Bal||');');
          end;
          else do;                                      /*如果余额不够此次消费,则存款,使得余额 等于 信用额度 */
            Tx_Amt=Bal-LIMIT_AMT;                       /*这里 Tx_Amt 表示存入的金额*/
            call execute('%repay(Cardnum='||Card_num||');');
          end;
    output;
  end;
  stop;
run;

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:EXECUTE data步 call Cute Data 信用卡还款 如何 信息

沙发
数据分析师3K 发表于 2012-8-21 17:53:33
为什么非得使用call execute?
这对于处理一些小的宏比较方便
如同主贴的情况则有些吃力了

藤椅
zengweixiong 发表于 2012-8-22 09:17:24
不一定非要。
要实现我现在的目的,有什么方法最好?

板凳
jingju11 发表于 2012-8-22 09:34:01
你的程序应该是对的啊,为什么要改呢?京剧

报纸
zengweixiong 发表于 2012-8-22 10:11:32
这是不对的   call execute是在执行完data之后才执行的。我需要 每次刷消费完之后要立刻更新余额 。

如果是 9.2版本也很容易解决这个问题 .参照下面文档
http://support.sas.com/resources ... ings12/227-2012.pdf

地板
jingju11 发表于 2012-8-22 10:45:43
我还是觉得你的没有什么错误。当然TRANS这个数据意义不大。你的程序不就是根据条件对不同的信用卡(有可能重复)反复更新吗?京剧

7
zengweixiong 发表于 2012-8-22 11:43:21
是更新  
涉及到同步(timing)问题   先看看我给出的链接。

8
zengweixiong 发表于 2012-8-22 17:19:34
自己回一个 ,稍微变通了下,用hash实现了,虽不能完全等同于上面的代码功能,但是相类似。代买如下

data cards;
  input Card_num $  LIMIT_AMT;
  After_Update_Bal=LIMIT_AMT;

datalines;
11111 1000
22222 2000
33333 3000
44444 4000
55555 5000
;
run;




data trans;
  if _N_ =0 THEN DO;
    SET CARDS;
        STOP;
  END;

  if _N_ = 1 then do;
     declare hash h(hashexp: 4);
     rc = h.defineKey('Card_num');
     rc = h.defineData('After_Update_Bal');
     rc = h.defineDone();
         call missing(Card_num, After_Update_Bal);
  end;
   do i=1 to 100;
        mycardpoint=CEIL(abs(rand('normal'))*mycardnobs/2);/* 模拟卡的使用情况,越前面的使用次数越多。正态分布 2个标准差*/
        if(mycardpoint>mycardnobs) then mycardpoint=CEIL(RANUNI(0)*mycardnobs);
        set Cards POINT=mycardpoint nobs=mycardnobs;

        /*先看表中有没有,如果有则用有的 */
    rc = h.find();
    if (rc ^= 0) then do;
          After_Update_Bal=LIMIT_AMT;
          rc = h.add();
        end;
    Tx_Amt=900;
    After_Update_Bal=After_Update_Bal-Tx_Amt;
        if(After_Update_Bal>=0) then do;
          rc = h.replace();
        end;
        else do;/*存款*/
          After_Update_Bal=After_Update_Bal+Tx_Amt;
          Tx_Amt=After_Update_Bal-LIMIT_AMT;
          After_Update_Bal=LIMIT_AMT;
          rc = h.replace();
        end;
    output;
  end;
  stop;
run;

9
zengweixiong 发表于 2012-8-22 17:27:13
如果要真正实现完全等价的代码 ,则再写一个大的宏,将里面的 do循环放在外面,同时将里面的call execute  提出来。每 执行一次do,产生一条数据,放在A数据集,将对应的余额放入 宏,在外面判断是消费 还是  存款 。
比较麻烦

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-30 06:08