转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件使用 >> 常用软件 >> 正文
select命令使用经验(2)         

select命令使用经验(2)

作者:闵涛 文章来源:闵涛的学习笔记 点击数:755 更新时间:2009/4/24 21:43:57
p class=left>【having的使用技巧】
  having参数一般是与group by参数使用,是告诉SQL将那些符合过滤条件的组别含入查询结果中。不过在条件式中不能包含一个子查询。但如果having不与group by一同使用时,它就与where参数类似。但两者有两个区别导致having是不会快过where参数的。
select的条件过滤的先后顺序是这样的(我是根据经验而猜得,不知对否):先对join中的on表达式进行过滤,再到where,中间结果出来后再用having进行过滤,最后才把结果显示出来。所以说having是对select结果的最后一次过滤。它与where的分别就是where能够事先把不要的数据过滤掉,这样select里头就不用处理那么多的数据。但有些数据事先不知道要不要过滤,要根据结果才能确定,这时才用having这个事后诸葛亮。但因为having是事后诸葛亮,对结果产生再进行条件筛选的,所以不能使用Rushmore,其效率可想而知有多高了。
这里兴修例子来比较一下on、where、having的不同之处
表recdbf内容如下:                还有一个tempyf的辅助表,记录12个月

日期 性质 yf 2000年7月3日 特大 1 2000年7月9日 特大 2 2000年9月3日 特大 3 1999年3月2日 一般 4 1999年3月4日 一般 5 2000年1月3日 一般 6 2000年2月1日 一般 td> 2000年2月3日 一般 8 2000年3月4日 一般 9 2000年8月7日 一般 10 2000年11月2日 一般 11 1999年2月3日 重大 12 2000年2月3日 重大 2000年5月2日 重大 2000年8月9日 重大

on的命令如下
SELECT tempyf.*,;
  SUM(IIF(ISNULL(recdbf.日期).OR.AT("一般",recdbf.性质)=0,0,1)) AS 一般,;
  SUM(IIF(ISNULL(recdbf.日期).OR.AT("重大",recdbf.性质)=0,0,1)) AS 重大,;
  SUM(IIF(ISNULL(recdbf.日期).OR.AT("特大",recdbf.性质)=0,0,1)) AS 特大;
 FROM tempyf LEFT OUTER JOIN recdbf ;
  ON tempyf.yf = MONTH(recdbf.日期).AND.YEAR(日期) = ?yy;
 GROUP BY tempyf.yf
其中yy=2000,表示统计2000年的数据
用where的命令如下:
SELECT tempyf.*,;
  SUM(IIF(ISNULL(recdbf.日期).OR.AT("一般",recdbf.性质)=0,0,1)) AS 一般,;
  SUM(IIF(ISNULL(recdbf.日期).OR.AT("重大",recdbf.性质)=0,0,1)) AS 重大,;
  SUM(IIF(ISNULL(recdbf.日期).OR.AT("特大",recdbf.性质)=0,0,1)) AS 特大;
 FROM tempyf LEFT OUTER JOIN recdbf ;
  ON tempyf.yf = MONTH(recdbf.日期);
 GROUP BY tempyf.yf ;
where YEAR(日期) = ?yy &&注意,条件从on移到这里来了
用having的命令如下:
SELECT tempyf.*,;
  SUM(IIF(ISNULL(recdbf.日期).OR.AT("一般",recdbf.性质)=0,0,1)) AS 一般,;
  SUM(IIF(ISNULL(recdbf.日期).OR.AT("重大",recdbf.性质)=0,0,1)) AS 重大,;
  SUM(IIF(ISNULL(recdbf.日期).OR.AT("特大",recdbf.性质)=0,0,1)) AS 特大;
 FROM tempyf LEFT OUTER JOIN recdbf ;
  ON tempyf.yf = MONTH(recdbf.日期);
 GROUP BY tempyf.yf ;
having YEAR(日期) = ?yy &&注意,条件从on移到这里来了
on的结果如下,这是正确的

YF 一般 重大 特大 1 1 0 0 2 2 1 0 3 1 0 0 4 0 0 0 5 0 1 0 6 0 0 0 7 0 0 2 8 1 1 0 9 0 0 1 10 0 0 0 11 1 0 0 12 0 0 0


用where的结果如下:

YF 一般 重大 特大 1 1 0 0 2 2 1 0 3 1 0 0 5 0 1 0 7 0 0 2 8 1 1 0

用having的结果如下:

YF 一般 重大 特大 1 1 0 0 2 2 2 0 5 0 1 0 7 0 0 2 8 1 1 0 9 0 0 1 11 1 0 0

各位看到有什么不同吗?
  on是把先把recdbf中不是2000年的记录过滤掉,剩下的就是2000年的了,再用tempyf去和它们进行外联接,其结果可用
sele tempyf.*,recdbf.日期 ;
from tempyf left join recdbf ;
ON tempyf.yf = MONTH(recdbf.日期).AND.YEAR(日期) = yy;
 GROUP BY tempyf.yf
  来查看,这个中间结果出来后,再用isnull把空值的记录变成0或1,然后由sum去统计,结果就出来了
而where呢,
  1、它是先把tempyf外联接recdbf, 相当于sele tempyf.*,recdbf.* from tempyf left join recdbf on tempyf.yf=mont(recdbf.日期)
  2、然后把不是2000的记录过滤掉,这里要注意的是,如果某个月没有记录的话,那在第一个步骤后日期那里是null值,这当然不是2000的记录,所以就给这个条件给过滤出去了,所以下一步的sum之后就只剩下那有记录的那个月了,象4、6月等几个月。就没有
  3、然后进行sum(……)

再看having
  1、第一步和where一样,
  2、第二步不同,它是先sum(),这里的sum可不管你是1999年还是2000的,先累加起来再说,这时,1999和2000年的2月份都有“重大”这个记录,sum的结果是2,这里用第三个步骤去分辨这个2之中那个是1999年的,那个是2000的,这当然分不清啦,所以也错了。
  3、根据步骤2来把2000的过滤出来。

  所以on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后。但有时候如果这先后顺序不影响中间结果的话,那最终结果是相同的。但因为on是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的。根据上面的分析,可以知道where也应该比having快点的,因为它过滤数据后才进行sum,所以having是最慢的。但也不是说having没用,因为有时在步骤3还没出来都不知道那个记录才符合要求时,就要用having了。

【自连接(self-joins)】
  在某些状况下,可能需要比较来自同一个表的两组信息才能获得所需的结果。例如:
  按业务员的销售额的高低顺序,显示每一个业务员的销售额,并伴随显示那些比他销售还多的业务员的平均销售额。
  select a.salesman,a.name,a.ytdsales,AVG(b.ytdsales) as better ;
from salesman A,salesman B ; &&这里把salesman打开两次,分别起个别名A和B
where A.ytdsales<B.ytdsales ;
grou by A.salesman ;
orde by A.ytdsales DESC

相同于使用联接:
  select a.salesman,a.name,a.ytdsales,AVG(B.ytdsales) as better ;
from salesman inner join salesman salesman_a ;
on salesman.ytdsales<salesman.ytdsales ;
grou by salesman.name ;
orde by salesman.dd desc

注:自连接时必须注意以下事项:
  1、同一来源数据库务必给予不同的别名;
  2、位于select命令语句的字段串列中各个字段前都必须中上别名;
  3、由于一旦自连接后即形成“多对多”的关联性连接,因此请小心设定where参数的连接条件。在一个

  有1千个记录的表中,执行第一条命令要188.261秒,第二条命令要154.712秒。而500个记录时,第一条命令6.870秒,第二条7.190秒。虽然其中的数值有点不是很准确,但这不重要,只要知道不要随便使用这种方法就行了。

下页8


[办公软件]在sybase中插入图片、PDF、文本文件  [办公软件]安装Sybase ASE
[办公软件]linux指令大全(完整篇)  [办公软件]Linux新手入门常用命令大全
[办公软件]在RedHat Linux 9里安装gaim0.80  [办公软件]浅谈Linux 下Java 1.5 汉字方块问题解决方法
[办公软件]Linux程序员必读:中文化与GB18030标准  [办公软件]linux指令大全
[办公软件]制作Linux启动盘的四种方法  [办公软件]Linux文件系统的反删除方法
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · 办公软件  · 系统软件
    · 常用软件  · 聊天工具
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台