CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  MS-SQL Server >  疑难问题

有关多关键字结构表的查询优化方案.

楼主drk928(一起看斜阳)2006-11-03 19:58:06 在 MS-SQL Server / 疑难问题 提问

由于公司需求特殊,  
  使用物料编码+型号规格为关键字,也就是说物料编码可以重复.  
  在出入库的时候还要加上颜色字段作为区分.而且资料表还有其它不下五个外键关联字段.  
  这样导致在做统计查询的时候速度很慢.  
  查询模式一般为在存储过程中使用如下SQL:  
  select   distinct   a.MatCode,a.Spec,a.ColorName,  
  InAmt=(select   sum(b.Amt)   From   vMatInout   b   where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and   b.Reason='入库'),  
  OutAmt=(select   sum(b.Amt)   From   vMatInout   b   where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and   b.Reason='出库'),  
  From   vMatIn   a    
  Group   By     a.MatCode,a.Spec,a.ColorName  
  Order   by     a.MatCode,a.Spec,a.ColorName  
   
  表我都根据查询建好了相应的索引.  
  我把出入库是放在同一张表的.用正负数来区分的.  
  目前资料表记录才13万多,感觉速度力不从心了.  
  有什么好的办法可以解决掉它?  
   
  问题点数:20、回复次数:16Top

1 楼vfssqs(lailailai)回复于 2006-11-04 09:36:52 得分 0

select   distinct   a.MatCode,a.Spec,a.ColorName,  
  InAmt=(select   sum(b.Amt)   From   vMatInout   b   where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and   b.Reason='入库'),  
  OutAmt=(select   sum(b.Amt)   From   vMatInout   b   where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and   b.Reason='出库'),  
  From   vMatIn   a    
  Group   By     a.MatCode,a.Spec,a.ColorName  
  Order   by     a.MatCode,a.Spec,a.ColorName  
   
  这一条SQL本身就有问题  
  distinct   本身就有分组的效果。而且再加上Order   by   还能快起来才怪  
   
  InAmt=(select   sum(b.Amt)   From   vMatInout   b   where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and   b.Reason='入库'),  
  OutAmt=(select   sum(b.Amt)   From   vMatInout   b   where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and   b.Reason='出库'),  
  而且要实现你这个功能,你这种写法是最差的一种。Top

2 楼vfssqs(lailailai)回复于 2006-11-04 09:41:08 得分 0

13万记录。不怎么多。Top

3 楼drk928(一起看斜阳)回复于 2006-11-06 14:18:59 得分 0

那你说说怎么写比较快呢?Top

4 楼test2002(test2002)回复于 2006-11-09 16:43:46 得分 0

建议如下使用  
   
  declare   @piInAmt   int,@piOutAmt   int  
  select   @piInAmt=sum(b.Amt)   From   vMatInout   b   where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and   b.Reason='入库'  
   
  select   @piInAmt=sum(b.Amt)     From   vMatInout   b   where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and   b.Reason='出库'  
   
   
  select   distinct   a.MatCode,a.Spec,a.ColorName,  
  @piInAmt,  
  @piOutAmt,  
  From   vMatIn   a    
  Group   By     a.MatCode,a.Spec,a.ColorName  
  Order   by     a.MatCode,a.Spec,a.ColorName  
   
  这样会很快的,10几万记录是很小的,几千万的记录,都不会慢Top

5 楼test2002(test2002)回复于 2006-11-09 17:19:38 得分 0

1.  
  select   distinct   a.MatCode,a.Spec,a.ColorName,  
  InAmt=  
  case   b.Reason  
    when   '入库'   then   sum(b.Amt)  
  end,  
   
  OutAmt=  
  case   b.Reason  
    when   '出库'   then   sum(b.Amt)  
  end,  
   
  From   vMatIn   a   ,  
  vMatInout   b  
  where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname    
  Group   By     a.MatCode,a.Spec,a.ColorName  
  Order   by     a.MatCode,a.Spec,a.ColorName  
   
  2\使用临时表,可能快些  
   
  select   MatCode,Spec,ColorName,sum(Amt)   as   InAmt   into   #temp   From   vMatInout     where   Reason='入库'  
  group   by   MatCode,Spec,ColorName  
   
   
   
  select   MatCode,Spec,ColorName,sum(Amt)   as   OutAmt   into   #temp1   From   vMatInout     where   Reason='出库'  
  group   by   MatCode,Spec,ColorName  
   
   
   
  select   distinct   a.MatCode,a.Spec,a.ColorName,  
  b.InAmt=  
  c.OutAmt  
  From   vMatIn   a   ,#temp   b,#temp1   c  
   
  where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname    
  a.MatCode=c.MatCode   and   a.Spec=c.Spec   and   a.ColorName=c.Colorname    
  Group   By     a.MatCode,a.Spec,a.ColorName  
  Order   by     a.MatCode,a.Spec,a.ColorName  
   
  你自己测试一下.Top

6 楼drk928(一起看斜阳)回复于 2006-11-10 11:05:41 得分 0

方法一:  
   
  服务器:   消息   8120,级别   16,状态   1,行   1  
  列   'b.reason'   在选择列表中无效,因为该列既不包含在聚合函数中,也不包含在   GROUP   BY   子句中。Top

7 楼drk928(一起看斜阳)回复于 2006-11-10 11:29:18 得分 0

declare   @piInAmt   int,@piOutAmt   int  
  select   @piInAmt=sum(b.Amt)   From   vMatInout   b   where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and   b.Reason='入库'  
   
  根本不支持这种写法.:  
  列前缀   'a'   与查询中所用的表名或别名不匹配。Top

8 楼test2002(test2002)回复于 2006-11-10 16:48:30 得分 0

select   distinct   a.MatCode,a.Spec,a.ColorName,  
  c.InAmt,  
   
  d.OutAmt,  
   
  From   vMatIn   a   ,  
  vMatInout   b,  
  (  
  select   MatCode,Spec,ColorName,sum(Amt)   as   InAmt   into   #temp   From   vMatInout     where   Reason='入库'  
  group   by   MatCode,Spec,ColorName  
   
  ) as   c,  
   
  (  
  select   MatCode,Spec,ColorName,sum(Amt)   as   OutAmt   into   #temp   From   vMatInout     where   Reason='出库'  
  group   by   MatCode,Spec,ColorName  
   
  ) as   d  
   
  where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and    
  a.MatCode=c.MatCode   and   a.Spec=c.Spec   and   a.ColorName=c.Colorname     and  
  a.MatCode=d.MatCode   and   a.Spec=d.Spec   and   a.ColorName=d.Colorname    
  Group   By     a.MatCode,a.Spec,a.ColorName  
  Order   by     a.MatCode,a.Spec,a.ColorName  
  Top

9 楼test2002(test2002)回复于 2006-11-10 16:54:22 得分 0

declare   @piInAmt   int,@piOutAmt   int  
  select   @piInAmt=sum(b.Amt)   From   vMatInout   b   where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname   and   b.Reason='入库'  
   
  根本不支持这种写法.:  
  列前缀   'a'   与查询中所用的表名或别名不匹配。  
  -----------------------------  
  我写错了  
  ,这样测试一下:  
   
  select   distinct   a.MatCode,a.Spec,a.ColorName,b.Reason,  
  InAmt=  
  case   b.Reason  
    when   '入库'   then   sum(b.Amt)  
  end,  
   
  OutAmt=  
  case   b.Reason  
    when   '出库'   then   sum(b.Amt)  
  end,  
   
  From   vMatIn   a   ,  
  vMatInout   b  
  where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname    
  and   (b.Reason="出库"or   b.Reason="入库")  
  Group   By     a.MatCode,a.Spec,a.ColorName,b.Reason  
  Order   by     a.MatCode,a.Spec,a.ColorName  
   
  这样肯定可以了,只是多了一列b.Reason  
  Top

10 楼test2002(test2002)回复于 2006-11-10 16:57:00 得分 0

select   里面的b.Reason去掉看看行不行,但group   by   里面肯定要加b.Reason的.Top

11 楼drk928(一起看斜阳)回复于 2006-11-13 16:00:36 得分 0

你那个distinct要本没有取到作用.它的结果是  
  a.MatCode,a.Spec,a.ColorName,b.Reason,InAmt,OutAmt为唯一的.有两条记录了.入库一条,出库一条.  
   
  Top

12 楼drk928(一起看斜阳)回复于 2006-11-13 16:09:39 得分 0

就是因为group   by   里加了reason,所以导致出来就是两条了.Top

13 楼drk928(一起看斜阳)回复于 2006-11-14 09:18:07 得分 0

运行成功.  
  但是你那个写法的速度还不够我原来的写法的速度快啊....  
  我的执行要2秒,而你的办法要5秒.Top

14 楼test2002(test2002)回复于 2006-11-14 10:14:13 得分 0

select   distinct   a.MatCode,a.Spec,a.ColorName,InAmt=  
  case   b.Reason  
    when   '入库'   then   sum(b.Amt)  
  end,  
   
  OutAmt=  
  case   b.Reason  
    when   '出库'   then   sum(b.Amt)  
  end,  
   
  From   vMatIn   a   ,  
  vMatInout   b  
  where   a.MatCode=b.MatCode   and   a.Spec=b.Spec   and   a.ColorName=b.Colorname    
  and   (b.Reason="出库"or   b.Reason="入库")  
  Group   By     a.MatCode,a.Spec,a.ColorName,b.Reason  
  Order   by     a.MatCode,a.Spec,a.ColorName  
   
  把select   中的b.Reason去掉应该也可以的,只在group   by   中加b.Reason,这个方法应该最快的  
   
  -----------------------------  
  我的哪个写法芽   ?  
  这个??  
  要修改,应该比你的快  
  select   distinct   a.MatCode,a.Spec,a.ColorName,  
  c.InAmt,  
   
  d.OutAmt,  
   
  From   vMatIn   a   ,  
  (  
  select   MatCode,Spec,ColorName,sum(Amt)   as   InAmt   From   vMatInout     where   Reason='入库'  
  group   by   MatCode,Spec,ColorName  
   
  ) as   c,  
   
  (  
  select   MatCode,Spec,ColorName,sum(Amt)   as   OutAmt   From   vMatInout     where   Reason='出库'  
  group   by   MatCode,Spec,ColorName  
   
  ) as   d  
   
  where    
  a.MatCode=c.MatCode   and   a.Spec=c.Spec   and   a.ColorName=c.Colorname     and  
  a.MatCode=d.MatCode   and   a.Spec=d.Spec   and   a.ColorName=d.Colorname    
  Order   by     a.MatCode,a.Spec,a.ColorName  
  ------------------------------  
  不要子集b,而且要搞错了,不用写入临时表的,把   into   #temp去掉,也不用Group   by   就行了,如果还不快的话,建议你表vMatIn     ,vMatInoutb  
  都加上联合索引MatCode+Spec+ColorName,  
   
  十几万条记录,100ms以内便可以出来查询结果  
  Top

15 楼test2002(test2002)回复于 2006-11-14 10:23:20 得分 20

实际上,只要索引建对了,你的方法,我这几种方法,怎么也不可能超过一秒的查询速度的。Top

16 楼drk928(一起看斜阳)回复于 2006-11-21 09:07:13 得分 0

你上面的写法实际上是先求了同条件下唯一合计,然后再连接.用临时表也可以做的.表已经建立了聚合索引了.因为matCode有时候过长.所以效率并不高.后来改成了用入库日期做索引.因为查询大部分是按日期先过滤,再按物料类别,物料编号等条件..Top

相关问题

关键词

得分解答快速导航

  • 帖主:drk928
  • test2002

相关链接

  • SQL Server类图书

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo