问题描述
有三个实体:gupiao,8个字段,2780条记录,属性表,8条记录,规则表,分别根据不同字段的值设有N条规则。用下面的方法,全部计算,至少10多分钟才计算完毕,有没有更好的办法!!请教publicActionResultAllCountDeFen(){List<gupiao>gpList=db.gupiao.ToList();foreach(vargpingpList){CountDefen(gp.ID);}}publicActionResultCountDeFen(intID){List<attribName>attList=db.attribName.ToList();//获取所有属性列表8个属性List<GuiZhe>gzList=newList<GuiZhe>();//定义规则列表gupiaogp=db.gupiao.Find(ID);//初始化股票实体double?intDeFen=0;foreach(varattinattList)//遍历属列列表{switch(att.属性名称){//判断属名名称case"户均持股比例"://根据属性名称所对应的评测ID,返回所有规则列表,按规则值min升序排列gzList=db.GuiZhe.Where(p=>p.评测ID==att.ID).OrderBy(p=>p.规则取值min).ToList();foreach(vargzingzList){//查询第一个符合条件的,取得得分,跳出循环。if(gp.户均持股比例<=gz.规则取值min&&gz.规则取值max==0){intDeFen+=gz.得分;break;}}//如果没有匹配的,则查询最后一个当前值大于规则值max,最大值得分if(gp.户均持股比例>gzList.Last(x=>x.规则取值max!=0).规则取值min)intDeFen+=gzList.Last(x=>x.规则取值max!=0).得分;break;case"总市值":gzList=db.GuiZhe.Where(p=>p.评测ID==att.ID).OrderBy(p=>p.规则取值min).ToList();//根据属性名称所对应的评测ID,返回所有规则列表//循环平规则,精确查询//intDeFen=gzList.Last(x=>x.规则取值min==g.户均持股比例).得分;foreach(vargzingzList){if(gp.总市值/100000000<=gz.规则取值min&&gz.规则取值max==0){intDeFen+=gz.得分;break;}//查到第一个符合条件的,跳出循环。}//查询最大值得分if(gp.总市值/100000000>gzList.Last(x=>x.规则取值max!=0).规则取值min)intDeFen+=gzList.Last(x=>x.规则取值max!=0).得分;break;case"风险系数":gzList=db.GuiZhe.Where(p=>p.评测ID==att.ID).OrderBy(p=>p.规则取值min).ToList();//根据属性名称所对应的评测ID,返回所有规则列表//循环平规则,精确查询//intDeFen=gzList.Last(x=>x.规则取值min==g.户均持股比例).得分;foreach(vargzingzList){if(gp.风险系数<=gz.规则取值min&&gz.规则取值max==0){intDeFen+=gz.得分;break;}//查到第一个符合条件的,跳出循环。}//查询最大值得分if(gp.风险系数>gzList.Last(x=>x.规则取值max!=0).规则取值min)intDeFen+=gzList.Last(x=>x.规则取值max!=0).得分;break;case"资产负债率":gzList=db.GuiZhe.Where(p=>p.评测ID==att.ID).OrderBy(p=>p.规则取值min).ToList();//根据属性名称所对应的评测ID,返回所有规则列表//循环平规则,精确查询//intDeFen=gzList.Last(x=>x.规则取值min==g.户均持股比例).得分;foreach(vargzingzList){if(gp.资产负债率<=gz.规则取值min&&gz.规则取值max==0){intDeFen+=gz.得分;break;}//查到第一个符合条件的,跳出循环。}//查询最大值得分if(gp.资产负债率>gzList.Last(x=>x.规则取值max!=0).规则取值min)intDeFen+=gzList.Last(x=>x.规则取值max!=0).得分;break;case"销售净利率":gzList=db.GuiZhe.Where(p=>p.评测ID==att.ID).OrderBy(p=>p.规则取值min).ToList();//根据属性名称所对应的评测ID,返回所有规则列表//循环平规则,精确查询//intDeFen=gzList.Last(x=>x.规则取值min==g.户均持股比例).得分;foreach(vargzingzList){if(gp.销售净利率<=gz.规则取值min&&gz.规则取值max==0){intDeFen+=gz.得分;break;}//查到第一个符合条件的,跳出循环。}//查询最大值得分if(gp.销售净利率>gzList.Last(x=>x.规则取值max!=0).规则取值min)intDeFen+=gzList.Last(x=>x.规则取值max!=0).得分;break;case"营收增长":gzList=db.GuiZhe.Where(p=>p.评测ID==att.ID).OrderBy(p=>p.规则取值min).ToList();//根据属性名称所对应的评测ID,返回所有规则列表//循环平规则,精确查询//intDeFen=gzList.Last(x=>x.规则取值min==g.户均持股比例).得分;foreach(vargzingzList){if(gp.营业增长率<=gz.规则取值min&&gz.规则取值max==0){intDeFen+=gz.得分;break;}//查到第一个符合条件的,跳出循环。}//查询最大值得分if(gp.营业增长率>gzList.Last(x=>x.规则取值max!=0).规则取值min)intDeFen+=gzList.Last(x=>x.规则取值max!=0).得分;break;case"销售毛利率":gzList=db.GuiZhe.Where(p=>p.评测ID==att.ID).OrderBy(p=>p.规则取值min).ToList();//根据属性名称所对应的评测ID,返回所有规则列表//循环平规则,精确查询//intDeFen=gzList.Last(x=>x.规则取值min==g.户均持股比例).得分;foreach(vargzingzList){if(gp.销售毛利率_<=gz.规则取值min&&gz.规则取值max==0){intDeFen+=gz.得分;break;}//查到第一个符合条件的,跳出循环。}//查询最大值得分if(gp.销售毛利率_>gzList.Last(x=>x.规则取值max!=0).规则取值min)intDeFen+=gzList.Last(x=>x.规则取值max!=0).得分;break;case"利润增长":gzList=db.GuiZhe.Where(p=>p.评测ID==att.ID).OrderBy(p=>p.规则取值min).ToList();//根据属性名称所对应的评测ID,返回所有规则列表//循环平规则,精确查询//intDeFen=gzList.Last(x=>x.规则取值min==g.户均持股比例).得分;foreach(vargzingzList){if(gp.营业利润增长率<=gz.规则取值min&&gz.规则取值max==0){intDeFen+=gz.得分;break;}//查到第一个符合条件的,跳出循环。}//查询最大值得分if(gp.营业利润增长率>gzList.Last(x=>x.规则取值max!=0).规则取值min)intDeFen+=gzList.Last(x=>x.规则取值max!=0).得分;break;}}//写入数据库(8个属性计算结果相加,intDefen)gp.最终得分=Convert.ToInt32(intDeFen);db.Entry(gp).State=EntityState.Modified;db.SaveChanges();returnRedirectToAction("Index");}
解决方案
本帖最后由 starfd 于 2015-11-30 09:26:30 编辑
解决方案二:
试试用System.Threading.Tasks.Parallel.ForEach()
解决方案三:
循环里套循环,数量怎么可能会小
解决方案四:
不要在循环里面查询,空间换时间,一次性读出来再计算能很快
解决方案五:
不要将数据的查询过程写在逻辑里,将你需要遍历的数据做成个集合先查好了,然后再去其中取来进行运算,不要再用的时候去现查。在一些需要用while循环的时候将其写到一个单独的线程里去执行。不要循环套循环。
解决方案六:
属性名称与股票表所有要计算的字段一一对应,规则表是根据属性名称(评测ID为外键),制定的得分规则,得分表是保存某一属性的得分,股票的最终得分是所有参与计算属性得分的的总和。股票全表计算的,才有了三层,循环。。foreach(vargpingplist)//循环所有股票{...foreach(varattinattList)//循环所有字段(根据属性表,该表的值与股票表一一对应,一般不做增加){switch(att.AttName)//判断属性名称,{case:"户均持股比例":gzlist=db.guizhe.where(x=>x.评测ID==att.ID;//查询该属性对应的规则(*规则是根据需要动态添加的).....后面代码略。。。}想请教,根据上图,我所能想到的解决方案就是这个思路,。。。能正常完成计算。。但执行下来结果很慢。有没有更好的解决方案!!
解决方案七:
不太明白规则表的作用不然可直接写查询指令求取全部综合计算结果,再用程序评价
解决方案八:
1.规则表中的最大最小值字段填写有差错2.另起一张临时表,将股票的个评测值依据规则表select后存入临时表中,根据评测,一只股票会有8个评测值,那么临时表的数据是2780*8条记录数据量不多,然后在根据评测表的权重对股票评测值进行sum操作得出股票视图。一般sql执行应该可以在三分钟左右执行完成
解决方案九:
直接用SQL吧,存储过程
解决方案十:
引用7楼byronqiji的回复:
1.规则表中的最大最小值字段填写有差错2.另起一张临时表,将股票的个评测值依据规则表select后存入临时表中,根据评测,一只股票会有8个评测值,那么临时表的数据是2780*8条记录数据量不多,然后在根据评测表的权重对股票评测值进行sum操作得出股票视图。一般sql执行应该可以在三分钟左右执行完成
规则表是动态的。会增加或修改评分规则。用你说的方法试过了。还是慢。。。。
解决方案十一:
读到datatable里处理,会很快
解决方案十二:
引用9楼westcars的回复:
Quote: 引用7楼byronqiji的回复:
1.规则表中的最大最小值字段填写有差错2.另起一张临时表,将股票的个评测值依据规则表select后存入临时表中,根据评测,一只股票会有8个评测值,那么临时表的数据是2780*8条记录数据量不多,然后在根据评测表的权重对股票评测值进行sum操作得出股票视图。一般sql执行应该可以在三分钟左右执行完成规则表是动态的。会增加或修改评分规则。用你说的方法试过了。还是慢。。。。
你的主外键是怎么设置的,sql语句贴出来,大概花时多少,你预计多少时间处理完成?
解决方案十三:
引用11楼byronqiji的回复:
Quote: 引用9楼westcars的回复:
Quote: 引用7楼byronqiji的回复:
1.规则表中的最大最小值字段填写有差错2.另起一张临时表,将股票的个评测值依据规则表select后存入临时表中,根据评测,一只股票会有8个评测值,那么临时表的数据是2780*8条记录数据量不多,然后在根据评测表的权重对股票评测值进行sum操作得出股票视图。一般sql执行应该可以在三分钟左右执行完成规则表是动态的。会增加或修改评分规则。用你说的方法试过了。还是慢。。。。
你的主外键是怎么设置的,sql语句贴出来,大概花时多少,你预计多少时间处理完成?
--------------------------------------------------------------股票表,主键ID,是得分表gupiaoID外键,属性表ID,主键,是得分与规则表外键,要计算每支票的8个评测值,举例一个评测标准,if(营业利润增长率<=10)return2;if(营业利润增长率>10&&营业利润增长率<=20)return4;if(营业利润增长率>20&&营业利润增长率<=30)return6if(营业利润增长率>30&&营业利润增长率<=50)return8;if(营业利润增长率>50)return10用select查询很难实现呀!
解决方案十四:
设有数据表Av96.670950.8382-621.1336规则表Rminmaxlevel5010100183001260016606020则查询selectA.*,(selectmax(level)fromRwhereA.v>=minorA.v>max)aslevelfromA得vlevel96.67092050.838218-621.1336并不需要用程序逐个查询再说规则是可变的,在程序里写死也是不妥的
解决方案十五:
引用12楼westcars的回复:
Quote: 引用11楼byronqiji的回复:
Quote: 引用9楼westcars的回复:
Quote: 引用7楼byronqiji的回复:
1.规则表中的最大最小值字段填写有差错2.另起一张临时表,将股票的个评测值依据规则表select后存入临时表中,根据评测,一只股票会有8个评测值,那么临时表的数据是2780*8条记录数据量不多,然后在根据评测表的权重对股票评测值进行sum操作得出股票视图。一般sql执行应该可以在三分钟左右执行完成规则表是动态的。会增加或修改评分规则。用你说的方法试过了。还是慢。。。。
你的主外键是怎么设置的,sql语句贴出来,大概花时多少,你预计多少时间处理完成?
--------------------------------------------------------------股票表,主键ID,是得分表gupiaoID外键,属性表ID,主键,是得分与规则表外键,要计算每支票的8个评测值,举例一个评测标准,if(营业利润增长率<=10)return2;if(营业利润增长率>10&&营业利润增长率<=20)return4;if(营业利润增长率>20&&营业利润增长率<=30)return6if(营业利润增长率>30&&营业利润增长率<=50)return8;if(营业利润增长率>50)return10用select查询很难实现呀!
用sql对规则表betweenminandmax就行了
解决方案:
selecta.代码,b.id,a.利润,c.得分froma,b,cwhereb.id=c.评测idand利润betweenc.minandc.max;要评估的每一列都做这样的查询然后放入临时表中,然后根据权重计算得分
解决方案:
别胡扯了!你没看到他的max大多是0吗?他的max只是标记超过了上限引用15楼byronqiji的回复:
selecta.代码,b.id,a.利润,c.得分froma,b,cwhereb.id=c.评测idand利润betweenc.minandc.max;要评估的每一列都做这样的查询然后放入临时表中,然后根据权重计算得分
解决方案:
引用16楼xuzuning的回复:
别胡扯了!你没看到他的max大多是0吗?他的max只是标记超过了上限Quote: 引用15楼byronqiji的回复:
selecta.代码,b.id,a.利润,c.得分froma,b,cwhereb.id=c.评测idand利润betweenc.minandc.max;要评估的每一列都做这样的查询然后放入临时表中,然后根据权重计算得分
数据有效性和代码可执行是两码事如果他把规则也写错了,是不是代码也是胡扯的?再说了,如果min,max字段是乱写的,是不是程序里都是靠截字符串来判断值大小的?