我现在需要计算一系统产品的生产成本:
数据库:access 2007
数据表:t_test
字段说明:
ID:自动编号
FType:产品型号
FNumber:生产中工序编号(不同型号产品生产过程中所需要的工序不同,有些需要4道工序,有的只要3道工序……)
FYield:各工序生产过程中的良率
FCost:各工序生产成本
FTotalCost:累积成本A[n](公式:A[n+1]=A[n]/FYield[n+1]+FCost[n+1]))
FNote:备注,说明FTotalCost的期望结果问题:怎么实现累积成本这个公式,执行完得到FTotalCost这一列期望结果
数据表格式如下:
看看图片能不能传上来:
如果图片不行:
请看这个表://ID    FType    FNumber    FYield    FCost    FTotalCost    FNote
//1      A         1          .99      98                     FTotalCost期望结果:98
//2      A         2          .98      200                    FTotalCost期望结果:98/0.98+200=300
//3      A         3          .97      300                    FTotalCost期望结果:300/0.97+300=609.28
//4      A         4          .96      400                    FTotalCost期望结果:609.28/0.96+400=1034.67
//5      B         1          .99      100                    FTotalCost期望结果:100
//6      B         2          .98      200                    FTotalCost期望结果:100/0.98+200=302.04
//7      B         3          .97      300                    FTotalCost期望结果:302.04/0.97+300=611.38
//8      C         1          .99      100                    FTotalCost期望结果:100
//9      C         2          .98      200                    FTotalCost期望结果:100/0.98+200=302.04
先谢谢各位关注,感激不尽,请帮帮我,如果可以加我QQ教我就更感激了:523028174

解决方案 »

  1.   

    sql2005开始支持递归了:cte
    但是不知道access是否支持可以加载到程序内存,由程序进行递归扫描而生成
      

  2.   

    谢谢你的回答,ACCESS里目前不支持CTE,
    加载到程序内存听起来好像比较复杂,我不会啊
      

  3.   

    搞一个UDF(用户自定义函数)计算,或建立存储过程计算,要么用Delphi算完,用参数传入。
      

  4.   

    哦,仔细看了一下,你这个不必递归
    可以程序循环执行
    for i:=1 to 4 do
      runsqlbylevel(i);prcedure runsqlbylevel(i);
    if i=1 then
    执行:'update t_test set FTotalCost=FCost where FNumber='+inttostr(i)
    else
    执行:'update t_test set FTotalCost=FCost+(select FYield*FCost from t_test where id=外部id-) where FNumber='+inttostr(i)--这个 外部id,不知道access怎么传进去,sqlserver的update可以有from
      

  5.   

    这个不需要递归吧,只需要把查询结果按照id进行排序
    用for 循环进行遍历运算即可
      

  6.   

    比如说 身边没环境,随手写个概念公式
    定义一个result:=0;
           rtype:=‘’;
    把第一条记录内容赋给这两条变量for 循环你的adoquery do
    begin
      if (rtype=ftype)
        begin
           result:=result/fyield+fcose;
        end
      else
        begin
           result:=fcost;
           rtype:=ftype 
        end; 
    end;
    然后这里用id和result更新你的数据
      

  7.   

    csdn又抽风了,我晕比如说 身边没环境,随手写个概念公式
    定义一个result:=0;
       rtype:=‘’;for 循环你的adoquery do
    begin
       if (rtype=ftype)
       begin
         result:=result/fyield+fcose;
       end
       else
       begin
         result:=fcost;
         rtype:=ftype  
      end;  
    然后这里用id和result更新你的数据
    end;
      

  8.   

    谢谢你的回答,请问这个如何一次计算出不同的FType的累积成本?
      

  9.   

    谢谢你的回答,这个看起来就是我想要的结果,我看看ACCESS能不能实现 ,我初学,不太熟悉
      

  10.   

    用Delphi代码计算,完成后将结果存入数据库。
      

  11.   

    可以实现的
    access链接用adoconnection和adoquery,更新数据用adocommand
    另外注意小数运算的四舍五入
      

  12.   

    谢谢你,我根据你的代码,修改成如下代码,但是有错,请大家看看代码有什么问题://根据前面导入数据计算累积成本,查询按自动编号排序
    procedure TFinput_ZZ.btnCalculateClick(Sender: TObject);
      var result : single ;
          rtype,sqlstr,productName  : string ;
          i : Integer;  begin
          result := 0;
          rtype := '';      with datamd.adocalculate do      //循环adoquerty
             begin
                 productName := Fieldbyname('FproductName').AsString;
                 for  i:=0   to   RecordCount do
                   begin
                   if(rtype = productName )  // FproductName即帖中FType
                      begin   //此处为377行
                      result := result/FYield + FActualCost;  //FActualCost即帖中FCost,这个等式是否有问题
                      end else
                        begin
                        result := FActualCost;
                        rtype := FproductName;
                        end;
                    with datamd.adoupdateProcess do    //更新 FCost_Accumulation,即帖中FTotalCost
                         begin
                           close;
                           sql.clear;
                           sqlstr := 'update t_productprocess  set FCost_Accumulation = ' + floattostr(result) + ' where FproductName = ' + rtype;
                           sql.Add(sqlstr);
                           execsql;
                         end;
                    end;
             end;
    end;编译显示错误为:
    1、377行:Missing operator or semicolon;
    2、378行:Undeclaed identifier :'FYield'  注:FYield/FproductName都是我ACCESS的字段名
    3、382行:Undeclaed identifier :'FproductName'
    4、could not compile used unit 'input_zz.pas'请帮我看看是怎么解决 ,先谢谢了
      

  13.   

    代码作了些修改:
    用了Fieldbyname//根据前面导入数据计算累积成本,查询按自动编号排序
    procedure TFinput_ZZ.btnCalculateClick(Sender: TObject);
      var result : single ;
          rtype,sqlstr,productName  : string ;
          i : Integer;  begin
          result := 0;
          rtype := '';      with datamd.adocalculate do      //循环adoquery
             begin
                 productName := Fieldbyname('FproductName').AsString;
                 for  i:=0   to   RecordCount do
                   begin
                   if(rtype = productName )  // FproductName即帖中FType
                      begin
                      result := result/Fieldbyname('FYield').Value + Fieldbyname('FActualCost').Value;  //FActualCost即帖中FCost
                      end else
                        begin
                        result := Fieldbyname('FActualCost').Value;
                        rtype := Fieldbyname('FproductName').AsString;
                        end;
                    with datamd.adoupdateProcess do    //更新 FCost_Accumulation,即帖中FTotalCost
                         begin
                           close;
                           sql.clear;
                           sqlstr := 'update t_productprocess  set FCost_Accumulation = ' + floattostr(result) + ' where FproductName = ' + rtype;
                           sql.Add(sqlstr);
                           execsql;
                         end;
                    end;
             end;
    end;这样编译就只剩两个错误:
    1、377行:Missing operator or semicolon;
    2、could not compile used unit 'input_zz.pas'不知道错在哪里,少个分号
      

  14.   

    function CalculateTotalCost(ADOQuery:TADOQuery):bool;
    var iFType,s:string;
        pFTotalCost:double;
        ErrCount:integer;
        CDSet:TClientDataSet;
        DSP:TDataSetProvider;
    begin
      Result:=false;
      if not ADOQuery.Active then exit;
      CDSet:=TClientDataSet.Create(nil);
      DSP:=TDataSetProvider.Create(nil);
      try
        ADOQuery.First;
        DSP.DataSet:=ADOQuery;
        CDSet.SetProvider(DSP);
        CDSet.Open;
        pFTotalCost:=0;
        CDSet.First;
        while not CDSet.Eof do begin
          if iFType<>CDSet.FieldByName('FType').AsString then begin
            iFType:=CDSet.FieldByName('FType').AsString;
            CDSet.Edit;
            CDSet.FieldByName('FTotalCost').AsVariant:=
            CDSet.FieldByName('FCost').AsInteger;
            CDSet.Post;
          end
          else begin
            s:=Format('%f',[pFTotalCost / CDSet.FieldByName('FYield').AsFloat
              + CDSet.FieldByName('FCost').AsInteger]);
            CDSet.Edit;
            CDSet.FieldByName('FTotalCost').AsFloat:=strtofloat(s);
            CDSet.Post;
          end;
          pFTotalCost:=CDSet.FieldByName('FTotalCost').AsInteger;
          CDSet.Next;
        end;
        if CDSet.ChangeCount>0 then begin
           DSP.ApplyUpdates(CDSet.Delta,0,ErrCount);
           Result:=true;
         end;
      finally
        CDSet.Free;
        DSP.Free;
      end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      if CalculateTotalCost(ADOQuery1)then showmessage('成本核算完成。')//ADOQuery1是你的查询数据集
      else showmessage('成本核算失败。');
    end;
      

  15.   

    嗯,我加了一个自动编号的字段ID,到时按ID排序,现在我正测试,哈哈,看起来肯定行了,
    马上向你报告我运行的结果
      

  16.   

    请问这个函数还在哪个地方声明一下吗?:function CalculateTotalCost(ADOQuery:TADOQuery):bool;我运行出错了
      

  17.   

    你的结果就是我想的!但是我不知道怎么编译不成功
    我的代码如下:unit input_zz;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, DBGridEhGrouping, GridsEh, DBGridEh, ExtCtrls, DBCtrls;type
      TFinput_ZZ = class(TForm)
        GroupBox1: TGroupBox;
        Label1: TLabel;
        cmbYear: TComboBox;
        cmbPeriod: TComboBox;
        lblfirst: TLabel;
        lblSecond: TLabel;
        lblThird: TLabel;
        edtNH: TEdit;
        edtWH: TEdit;
        edtSL: TEdit;
        btnSave: TButton;
        btnClear: TButton;
        GroupBox2: TGroupBox;
        Label8: TLabel;
        Label9: TLabel;
        btnSelectAndInput: TButton;
        btnmodify: TButton;
        Label6: TLabel;
        Label10: TLabel;
        Label11: TLabel;
        lblUnit3: TLabel;
        lblFourth: TLabel;
        edtRs: TEdit;
        lblUnit4: TLabel;
        cmbFactory: TComboBox;
        Label2: TLabel;
        GroupBox3: TGroupBox;
        Label3: TLabel;
        Label4: TLabel;
        btnInputZCB: TButton;
        btnModifyprocess: TButton;
        btnCalculate: TButton;
        cmbproductName: TComboBox;
        procedure btnSaveClick(Sender: TObject);
        procedure btnClearClick(Sender: TObject);
        procedure edtNHKeyPress(Sender: TObject; var Key: Char);
        procedure cmbFactoryChange(Sender: TObject);
        procedure btnSelectAndInputClick(Sender: TObject);
        procedure btnmodifyClick(Sender: TObject);
        procedure btnModifyprocessClick(Sender: TObject);
        procedure btnInputZCBClick(Sender: TObject);
        procedure btnCalculateClick(Sender: TObject);  private
        { Private declarations }
      public
      function CalculateTotalCost(ADOQuery:TADOQuery):bool;   //这个声明位置似乎不对
    { Public declarations }
      end;
    var
      Finput_ZZ: TFinput_ZZ;implementationUSES data,productproperty,process;{$R *.dfm}
    function TFinput_ZZ.CalculateTotalCost(ADOQuery: TADOQuery): bool;
    var iFType,s:string;
        pFTotalCost:double;
        ErrCount:integer;
        CDSet:TClientDataSet;
        DSP:TDataSetProvider;
    begin
      Result:=false;
      if not ADOQuery.Active then exit;
      CDSet:=TClientDataSet.Create(nil);
      DSP:=TDataSetProvider.Create(nil);
      try
        ADOQuery.First;
        DSP.DataSet:=ADOQuery;
        CDSet.SetProvider(DSP);
        CDSet.Open;
        pFTotalCost:=0;
        CDSet.First;
        while not CDSet.Eof do begin
          if iFType<>CDSet.FieldByName('FproductName').AsString then begin
            iFType:=CDSet.FieldByName('FproductName').AsString;
            CDSet.Edit;
            CDSet.FieldByName('FCost_Accumulation').AsVariant:=
            CDSet.FieldByName('FActualCost').AsInteger;
            CDSet.Post;
          end
          else begin
            s:=Format('%f',[pFTotalCost / CDSet.FieldByName('FYield').AsFloat
              + CDSet.FieldByName('FActualCost').AsInteger]);
            CDSet.Edit;
            CDSet.FieldByName('FCost_Accumulation').AsFloat:=strtofloat(s);
            CDSet.Post;
          end;
          pFTotalCost:=CDSet.FieldByName('FCost_Accumulation').AsInteger;
          CDSet.Next;
        end;
        if CDSet.ChangeCount>0 then begin
           DSP.ApplyUpdates(CDSet.Delta,0,ErrCount);
           Result:=true;
         end;
      finally
        CDSet.Free;
        DSP.Free;
      end;
    end;
    end.
      

  18.   

    把函数放在调用的事件前,就不用声明,否则,这样声明:
    type
      TForm1 = class(TForm)
        Edit1: TEdit;
      private
        { Private declarations }
        function CalculateTotalCost(ADOQuery:TADOQuery):bool;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}function TForm1.CalculateTotalCost(ADOQuery:TADOQuery):bool;
    begin
    ...
    end;
    注意函数体与声明的格式有区别噢:
    function TForm1.CalculateTotalCost(ADOQuery:TADOQuery):bool;
      

  19.   

    我明白你的问题出在单元引用上:
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Grids, DBGrids, DB, DBClient, StdCtrls, Provider, ADODB,MidasLib;{使用TClientDataSet时,引用MidasLib单元,就不用发布Midas.dll}对比你缺的补充下
      

  20.   

    主要是 Provider, DB, DBClient 这三个组件
      

  21.   

    还是有编译错误:请您看我代码,我声明了函数…… 
    private
        { Private declarations }
        function CalculateTotalCost(ADOQuery: TADOQuery): bool;   //56行声明函数,格式不同
      public{ Public declarations }
      end;implementationUSES data,productproperty,process;{$R *.dfm}function TFinput_ZZ.CalculateTotalCost(ADOQuery: TADOQuery): bool;
    var iFType,s:string;
        pFTotalCost:double;
        ErrCount:integer;
        CDSet:TClientDataSet;   //第377行
        DSP:TDataSetProvider;   //第378行
    begin
      Result:=false;
      if not ADOQuery.Active then exit;
      CDSet:=TClientDataSet.Create(nil);
      DSP:=TDataSetProvider.Create(nil);
      try
        ADOQuery.First;
        DSP.DataSet:=ADOQuery;
        CDSet.SetProvider(DSP);
        CDSet.Open;
        pFTotalCost:=0;
        CDSet.First;
        while not CDSet.Eof do begin
          if iFType<>CDSet.FieldByName('FproductName').AsString then begin
            iFType:=CDSet.FieldByName('FproductName').AsString;
            CDSet.Edit;
            CDSet.FieldByName('FCost_Accumulation').AsVariant:=
            CDSet.FieldByName('FActualCost').AsInteger;
            CDSet.Post;
          end
          else begin
            s:=Format('%f',[pFTotalCost / CDSet.FieldByName('FYield').AsFloat
              + CDSet.FieldByName('FActualCost').AsInteger]);
            CDSet.Edit;
            CDSet.FieldByName('FCost_Accumulation').AsFloat:=strtofloat(s);
            CDSet.Post;
          end;
          pFTotalCost:=CDSet.FieldByName('FCost_Accumulation').AsInteger;
          CDSet.Next;
        end;
        if CDSet.ChangeCount>0 then begin
           DSP.ApplyUpdates(CDSet.Delta,0,ErrCount);
           Result:=true;
         end;
      finally
        CDSet.Free;
        DSP.Free;
      end;
    end;//根据前面导入数据计算累积成本,查询按自动编号排序
    procedure TFinput_ZZ.btnCalculateClick(Sender: TObject);
     
    begin
      if CalculateTotalCost(datamd.adocalculate)then showmessage('成本核算完成。')//ADOQuery1是你的查询数据集
      else showmessage('成本核算失败。');
    end;end.
    编译错误:说
    56行,也就是声明函数那一行:Undeclared identifier 'TADOQuery'
    还有377行:Undeclared identifier 'TClientDataSet'
    还有378行:Undeclared identifier 'TDataSetProvider'
    ……
      

  22.   

    晕,你的单元里连'TADOQuery'都无?!你干脆给个邮箱,我把工程发给你慢慢看,我有紧要事做,要下了。
      

  23.   

    好的,哈哈,谢谢你
    [email protected]
    正如你所说,单元引用里没有adodb,我在uses里加上adoDB后,能正确运行了,不过所有的记录都是0,
    请你把工程发给我让我好好学习一下吧,谢谢你了
    不好意思,耽误你时间了