SAS中文论坛

标题: 再问下“死猪头” :D [打印本页]

作者: shiyiming    时间: 2009-8-5 09:42
标题: 再问下“死猪头” :D
<!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D --> 如果我现在是求每次采购的商品的加权平均库存时间,对你那个程序稍微改动一下就可以实现,不过必须对数据进行适当排序(一定要卖出排在采购前面)才行,程序附后。

[color=#800000:1sub4pu6]现在的问题是:[/color:1sub4pu6] 由于我的实际数据比较复杂,比如第8行(Note=0),那120个商品是供应商免费送的(不能单独计算其库存时间),需要把他分配到还没卖完的进货批次中(无需其他的操作)。具体来说,供应商免费送货只分配给还没卖完的进货批次,按照加权平均的原则分配。比如如果供应商免费送货之前还有2次的进货还没卖完,假设免费送货数量为x,两次没卖完的进货声誉数量分别为y1和y2,那么y1=y1+x*y1/(y1+y2), y2=y2+x*y2/(y1+y2) 。如果送货之前有更多次的进货没卖完,按照相同的方法分配。

另外,对于还没有卖完的进货,其库存时间也是不必计算的。

数据说明:ID为商品编号,Date为采购或卖出时间,Num为采购或卖出数量,Act识别是采购还是卖出, Note是备注。

data a;
input ID$ Date yymmdd8. Num Act Note;
format Date yymmdd10.;
cards;
001 08-07-01 100 1 .
001 08-07-02 20  0 .
001 08-07-05 100  1 .
001 08-07-06 80  0 .
001 08-07-07 40  0 .
001 08-07-08 40  0 .
001 08-07-09 100  1 .
001 08-07-10 120  1 0
001 08-07-12 240  0 .
002 08-07-01 100  1 .
002 08-07-02 20  0 .
002 08-07-05 80  0 .
002 08-07-06 100  1 .
002 08-07-08 50  0.
;

proc sort data=a;
  by ID Act;

%let QUEUE_SIZE=1000;
data zhutou(drop = head tail tmp_num total);
   array queue[0:&amp;QUEUE_SIZE, 1:2] _temporary_;
   head = 0;
   tail = -1;
   do until(last.id);
      set a end=eof;
      by id;
      if Act=0 then do;
         tail = mod(tail+1, &amp;QUEUE_SIZE);
         if mod(tail+1, &amp;QUEUE_SIZE) = head then do;
            put &quot;Error - QUEUE overflow: bigger QUEUE_SIZE wanted&quot;;
            stop;
         end;
         queue[tail,1] = num;
         queue[tail,2] = date;
         avg = .;
      end;
      else do;
         total = 0;
         tmp_num = num;
         do while(tmp_num &gt; 0 and head ne mod(tail+1, &amp;QUEUE_SIZE));
            if tmp_num&gt;queue[head,1] then do;
               tmp_num = tmp_num-queue[head,1];
               total = total + queue[head,1]*(-date+queue[head,2]);
               queue[head,1]=0;
               head = mod(head+1, &amp;QUEUE_SIZE);
                           if head = mod(tail+1, &amp;QUEUE_SIZE) then do;
                  avg = .;
                       end;
               else do;
                  avg = total / num;
               end;
            end;
            else do;
               total = total + tmp_num*(-date+queue[head,2]);
               queue[head,1] = queue[head,1]-tmp_num;
               tmp_num=0;
                           avg = total / num;
            end;
         end;
      end;
      output;
   end;
run;
作者: shiyiming    时间: 2009-8-5 20:53
标题: Re: 再问下“死猪头” :D
怎么这么像猪头的领导,什么都没交待清楚就要柱头动手,猪头之所以是猪头就是因为能力比是个人都低。加了免费或之后库存时间怎么算,结果到底要几条记录,他们都长啥样?
作者: shiyiming    时间: 2009-8-6 13:58
标题: Re: 再问下“死猪头” :D
哈哈,谢谢猪头 <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->  <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->

免费的送货直接分配给以前还没卖完的进货批次中,只改变以前个进货批次的剩余数量,而不改变其进货的日期。

结果是计算每个ACT=1(但Note不为0)的记录的平均库存时间,比如:
第一行:100个商品分别在第2、4行卖完,加权平均库存时间为:(20×1+80×5)/100=4.2;
第三行:100个商品分别在第5、6行卖出了80个,剩下20个,但在下一次卖出前有一次免费送120个商品((第8行)),这120个按加权平均分配到第3行和第7行中,其中第3行分到120*20/(100+20)=20个,第7行分到120*100/(100+20)=100个,因此第3行实际剩下20+20=40个,这40个在第9行卖出。因此第三行的库存时间为:(40×2+40×3+40×7)/120=4;
第七行,进货100个,加上第8行送的100,一共200,全部在第9行卖出,库存时间为3天。
第十行,和第一行一样,库存时间为4,2。
第十三行,由于没卖完,因此不必计算。
作者: shiyiming    时间: 2009-8-7 09:00
标题: Re: 再问下“死猪头” :D
可以做,但是你那平均库存时间的定义实在不感恭维!

钢鞭男来了,快闪!
作者: shiyiming    时间: 2009-8-7 16:17
标题: Re: 再问下“死猪头” :D
老夫来凑个热闹
[code:3bxnwdd4]data store(keep=id date orinum num) sellandgift(keep=id date num act note);
    input ID$ Date yymmdd8&#46; Num Act Note ;
    if act=1 then oriNum=Num;
    format Date yymmdd10&#46;;
    if act=1 and note=&#46; then output store;
    else  output sellandgift;
    datalines;
001 08-07-01 100 1 &#46;
001 08-07-02 20 0 &#46;
001 08-07-05 100 1 &#46;
001 08-07-06 80 0 &#46;
001 08-07-07 40 0 &#46;
001 08-07-08 40 0 &#46;
001 08-07-09 100 1 &#46;
001 08-07-10 120 1 0
001 08-07-12 240 0 &#46;
002 08-07-01 100 1 &#46;
002 08-07-02 20 0 &#46;
002 08-07-05 80 0 &#46;
002 08-07-06 100 1 &#46;
002 08-07-08 50 0&#46;
;
run;
%let offsetid=0;
data allavg;   
    length id $8 Orinum num date offnum diff 8;
run;
%macro updateStore(num,note,id,selldate) ;
  %let offsetid=%eval(&amp;offsetid+1);
  %if &amp;note eq %then
    %do;
    data store(keep=id date num    orinum   ) avg(keep=id date OriNum offnum num     diff);
        left=0;
        set store ;
        by id date;
        retain number &amp;num  ;
        if id=&amp;id then  do;
          offnum=min(num,number);
          num=num-offnum;
          number=number-offnum;
          diff=(&amp;selldate-date);
        end;
        if offnum&gt;0 then output avg;
        if num&gt;0 then output store;
    run;

     proc append base=allavg
          data=avg force;
     run;
    %end;
  %if &amp;note=0 %then
    %do;
    proc sql;
      create table store(drop=oldnum ) as
      select *,oldnum+oldnum/sum(oldnum)*&amp;num*(id=&quot;&amp;id&quot;) as num
      from store(rename=(num=oldnum ))
      group by id
      order by id,date;
    %end;
%mend;

data _null_;
  set sellandgift;
  call execute('%updateStore('||num||','||note||','||id||','||date||')');
run;

proc sql;
    create table final as
    select  distinct id, date format=yymmdd10&#46;, oriNum,sum(diff*offnum)/sum(offnum) as avgdiff
    from allavg
    group by id,date
    having min(num)=0
    order by id,date;
[/code:3bxnwdd4]
作者: shiyiming    时间: 2009-8-7 20:11
标题: Re: 再问下“死猪头” :D
谢谢死猪头啊 <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->  <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->
你的程序怎么不见了??
作者: shiyiming    时间: 2009-8-7 20:13
标题: Re: 再问下“死猪头” :D
to ahuige

谢谢。
老大是不是贴错了,这个程序运行不出结果呢 <!-- s:o --><img src="{SMILIES_PATH}/icon_surprised.gif" alt=":o" title="Surprised" /><!-- s:o -->  <!-- s:o --><img src="{SMILIES_PATH}/icon_surprised.gif" alt=":o" title="Surprised" /><!-- s:o -->
作者: shiyiming    时间: 2009-8-10 02:16
标题: Re: 再问下“死猪头” :D
&quot;因此第三行的库存时间为:(40×2+40×3+40×7)/120=4;
第七行,进货100个,加上第8行送的100,一共200,全部在第9行卖出,库存时间为3天。&quot;
这解释得是不是有问题啊?

第三行是买入怎么会有库存时间?
在赠送之前 有第3行库存量20和第七行库存量100没有买出,所以第三行库存修正为20+120*20/(20+100)=40,第七行修正为100+120*100/(20+100)=200
第九行全部卖出库存时间应该是7*40/240+3*200/240=3.6666
作者: shiyiming    时间: 2009-8-10 15:55
标题: Re: 再问下“死猪头” :D
to 4772814
我要的其实是一次进货平均多少天可以卖完~~ <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->  <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->  <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->
作者: shiyiming    时间: 2009-8-12 22:28
标题: Re: 再问下“死猪头” :D
这业务需求啊,回去想想。呵呵
作者: shiyiming    时间: 2009-8-13 13:03
标题: Re: 再问下“死猪头” :D
to ganshenme

”运行不出结果“-----这句话从来且将来也永远是一句让人除了苦笑而没法进一步提供进一步帮助的回复。运行不出结果是1SAS运行报错呢?2.是没有任何输出呢?3是输出的结果不知道在哪个数据集中找呢?4,是数据集中都是空值呢?还是你用写字板来运行的这段程序呢?等了一周你都没反应过来?
作者: shiyiming    时间: 2009-8-14 06:33
标题: Re: 再问下“死猪头” :D
钢鞭男莫急!你的某一行少了一点。
作者: shiyiming    时间: 2009-8-14 10:18
标题: Re: 再问下“死猪头” :D
甚是奇怪,我直接从贴子里COPY代码出来RUN,没有什么异常。难道我的SAS9有纠错功能? 还是浏览器的显示问题?我用的MAXTHON。
作者: shiyiming    时间: 2009-8-14 11:27
标题: Re: 再问下“死猪头” :D
你可能有
[code:3bkv8z81]
options missing='';
[/code:3bkv8z81]
但是对我们这样的常人来说,一般是
[code:3bkv8z81]
options missing=&#46;;
[/code:3bkv8z81]
作者: shiyiming    时间: 2009-8-14 12:47
标题: Re: 再问下“死猪头” :D
奇怪,我的代码中好像没用OPTION啊?没这句话啊?难道你们看到的代码和我看的不一样?不说了。果然是有什么问题。老夫夜观天象,恐有异事。。。。。。。。
作者: shiyiming    时间: 2009-8-19 21:29
标题: Re: 再问下“死猪头” :D
to ahuige

老大,不好意思,最近被搞去干别的事情去了,好多天没来了 <!-- s:) --><img src="{SMILIES_PATH}/icon_smile.gif" alt=":)" title="Smile" /><!-- s:) -->  <!-- s:) --><img src="{SMILIES_PATH}/icon_smile.gif" alt=":)" title="Smile" /><!-- s:) -->  <!-- s:) --><img src="{SMILIES_PATH}/icon_smile.gif" alt=":)" title="Smile" /><!-- s:) -->
你那个程序运行没有错,但是产生的那个allavg表是个空的,最后得到的final表也是空的。

我看到的代码也是没有用option的,猪头怎么到看的,好奇怪啊 <!-- s:shock: --><img src="{SMILIES_PATH}/icon_eek.gif" alt=":shock:" title="Shocked" /><!-- s:shock: -->  <!-- s:shock: --><img src="{SMILIES_PATH}/icon_eek.gif" alt=":shock:" title="Shocked" /><!-- s:shock: -->
作者: shiyiming    时间: 2009-8-19 21:39
标题: Re: 再问下“死猪头” :D
你试试,如果只是运行我的样式代码结果应该是有的,和以前猪头的程序的结果可以对照一下。如果用到你的数据上不成功,那你得按相应的不同点去tailor.
作者: shiyiming    时间: 2009-8-19 21:41
标题: Re: 再问下“死猪头” :D
to ahuige

我就是直接copy你的程序运行的,最后得到的Allavg和Final两个表都是空的~
作者: shiyiming    时间: 2009-8-19 22:01
标题: Re: 再问下“死猪头” :D
直说了罢,要么在开头加[code:3jrvgqqk]options missing=''[/code:3jrvgqqk]
要么在[code:3jrvgqqk]%if &amp;note eq %then[/code:3jrvgqqk] 这一行加一个点。
版主写了这么漂亮的程序,你都不认真读一下,简直猪头都不如!

PS:我这人最大的缺点就是说话太值。
作者: shiyiming    时间: 2010-12-10 18:35
标题: Re: 再问下“死猪头” :D
呵呵,很久没有写东西了,写出来的都像垃圾,没有检查,没有优化。
[code:2c4ajr1l]
data a;
input ID$ Date yymmdd8&#46; Num Act Note;
format Date yymmdd10&#46;;
cards;
001 08-07-01 100 1 &#46;
001 08-07-02 20 0 &#46;
001 08-07-05 100 1 &#46;
001 08-07-06 80 0 &#46;
001 08-07-07 40 0 &#46;
001 08-07-08 40 0 &#46;
001 08-07-09 100 1 &#46;
001 08-07-10 120 1 0
001 08-07-12 240 0 &#46;
002 08-07-01 100 1 &#46;
002 08-07-02 20 0 &#46;
002 08-07-05 80 0 &#46;
002 08-07-06 100 1 &#46;
002 08-07-08 50 0&#46;
;
run;
data c(keep=date sell InStckDt lsting );
array stock{0&#58;9} _temporary_ (10*0); /*stock Amount*/
array dt{0&#58;9}  _temporary_ (10*0); /*Stocking date*/
retain StckNo 0; /*Stock number*/
set a(where=(ID=&quot;001&quot;));
if act=1 then do;
        if note=0 then do;
                TotStck=0;
                i=StckNo;
                do while(i&gt;=0);
                        TotStck=TotStck+stock{i};
                        i=i-1;
                end;
                i=StckNo;
                do while(i&gt;=0);
                        stock{i}=stock{i}+Num*stock{i}/TotStck;
                        i=i-1;
                end;
        end;
        else do;
                StckNo+1;
                i=StckNo;
                do while(i&gt;0);
                        stock{i}=stock{i-1};
                        dt{i}=dt{i-1};
                        i=i-1;
                end;
                stock{0}=num;
                dt{0}=date;
        end;
end;

if act=0 then do;
        t=num;
        i=StckNo-1;
        do while(i&gt;=0);
                u=stock{i};
                stock{i}=max(stock{i}-t,0);
                t=t-u;
                put i=;
                if stock{i}=0 then StckNo=StckNo-1;
                if stock{i}&lt;u then do;
                        lsting=datdif(dt{i},date,'act/act');
                        sell=u-stock{i};
                        InStckDt=dt{i};
                        output c;
                end;
                if stock{i}=0 then dt{i}=0;
                if t=0 then return;
                i=i-1;
        end;
end;
format InStckDt yymmdd10&#46;;
run;
[/code:2c4ajr1l]




欢迎光临 SAS中文论坛 (https://mysas.net/forum/) Powered by Discuz! X3.2