日期:2014-05-17  浏览次数:20421 次

sql优化
问题如下:查询的sql语句会调用GetStandardPrice函数取一个标准的价格,该函数中的MPS_MatPriceHistory表 有100多万条记录,
最终导致查询的效率非常低,查询大概花时间40秒。请各位大侠给出建议,如何优化这个sql.

--查询的sql语句如下:(说明:该sql放在存储过程中)
-select 
  cast(a.unitprice as decimal(18,4)) Unitprice, 
cast(dbo.GetStandardPrice(a.MaterialID,convert(nvarchar,b.ApproveEndDt,23),B.BussinessID)
as decimal(18,4)
  )''StandardPrice''
from dbo.MPS_ProcureDetail a 
inner join MPS_Procurement b on a.ProcureID=b.ProcureID
inner join MPS_material c on c.MaterialID=a.MaterialID
inner join sys_user d on d.id=b.createbyid

--取值函数如下:(求最标准价格)
ALTER FUNCTION [dbo].[GetStandardPrice]
  (
  @MaterialID varchar(20),--材料ID
  @ProApproveDate varchar(20),--时间
  @CurrentBussinessID varchar(20)--地区标志
  )
RETURNS decimal(18,4)
AS
BEGIN
  DECLARE @StandardPrice decimal(18,4)
  DECLARE @MinPrice decimal(18,4)
  declare @counts int 

  set @counts=0
  ---价格库里该材料的价格个数
select @counts=count(*),
  @MinPrice=Min(UnitPrice)
from MPS_MatPriceHistory t 
where t.MaterialID= @MaterialID
AND @ProApproveDate BETWEEN convert(nvarchar, t.StartDt,23) and t.EndDt
and unitprice >0.0000

  --至少存在2个价格,直接返回最小价格
  if @counts >=2
  begin  
  return @MinPrice
  end 
  --只存在一个价格,取其他2地的最近的最小的价格与该地区价格相比,标准价格为其中最小的。
  else if @counts >=1
  begin
select top 1
@StandardPrice=MIN(UnitPrice)
from MPS_MatPriceHistory t2
where t2.MaterialID= @MaterialID
and t2.BussinessID<>@CurrentBussinessID
and t2.unitprice >0.0000
and t2.EndDt<=Convert(datetime,@ProApproveDate)

if @StandardPrice>=@MinPrice 
return @MinPrice
else if @StandardPrice<>0 
return @StandardPrice
else --另外2地找不到价格
return -1
  end  
  --不存在价格
  return -1  
end

------解决方案--------------------
MaterialID 增加索引,聚合索引最好
------解决方案--------------------
@ProApproveDate BETWEEN convert(nvarchar, t.StartDt,23) and t.EndDt

把EndDt转换成datetime 取值效果会更高。
------解决方案--------------------
AND @ProApproveDate BETWEEN convert(nvarchar, t.StartDt,23) and t.EndDt

这个处理是很有问题的,EndDt是什么类型

你要保证数据类型一致