SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 2087|回复: 19
打印 上一主题 下一主题

再问下“死猪头” :D

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2009-8-5 09:42:31 | 只看该作者

再问下“死猪头” :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;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2009-8-5 20:53:21 | 只看该作者

Re: 再问下“死猪头” :D

怎么这么像猪头的领导,什么都没交待清楚就要柱头动手,猪头之所以是猪头就是因为能力比是个人都低。加了免费或之后库存时间怎么算,结果到底要几条记录,他们都长啥样?
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2009-8-6 13:58:28 | 只看该作者

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。
第十三行,由于没卖完,因此不必计算。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2009-8-7 09:00:16 | 只看该作者

Re: 再问下“死猪头” :D

可以做,但是你那平均库存时间的定义实在不感恭维!

钢鞭男来了,快闪!
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2009-8-7 16:17:38 | 只看该作者

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]
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
6#
 楼主| 发表于 2009-8-7 20:11:47 | 只看该作者

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 -->
你的程序怎么不见了??
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
7#
 楼主| 发表于 2009-8-7 20:13:28 | 只看该作者

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 -->
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
8#
 楼主| 发表于 2009-8-10 02:16:10 | 只看该作者

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
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
9#
 楼主| 发表于 2009-8-10 15:55:20 | 只看该作者

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 -->
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
10#
 楼主| 发表于 2009-8-12 22:28:59 | 只看该作者

Re: 再问下“死猪头” :D

这业务需求啊,回去想想。呵呵
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|小黑屋|手机版|Archiver|SAS中文论坛  

GMT+8, 2025-6-13 19:37 , Processed in 0.115507 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表