友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
狗狗书籍 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

SQL语言艺术(PDF格式)-第19章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




count(distinct decode(amount_diff;0;chr(1);account))…1 

bad_acct_count 

from 

glreport 

groupby 

deptnum; 

ledger; 

accounting_period 

这个新的查询,执行速度是原先的四倍。这丝毫不令人意外,因为三次的完整扫描变成了一次。 

注意,查询中不再有where子句:amount_diff上的条件已被“迁移”到了select列表中decode()函数 

执行的逻辑,以及由groupby子句执行的聚合(aggregation)中。 



使用聚合代替过滤条件有点特殊,这正是我们要说明的“九种典型情况”中的另一种—— 以聚合 

函数为基础获得结果集。 

总结:内嵌查询可以简化查询,但若使用不慎,可能造成重复处理。 



小结果集,间接条件 



Small Result Set; Indirect Criteria 



与上一节类似,这一节也是要获取小结果集,只是查询条件不再针对源表,而是针对其他表。 

我们想要的数据来自一个表,但查询条件是针对其他表的,且不需要从这些表返回任何数据。 

典型的例子是在第4章讨论过的“哪些客户订购了特定商品”问题。如第4章所述,这类查询可用 

两种方法表达: 



使用连接,加上 distinct 去除结果中的重复记录,因为有的客户会多次订购相同商品 

使用关联或非关联子查询 



如果可以使用作用于源表的条件,请参考前一节“小结果集,直接条件”中的方法。但如果找不 

到这样的条件,就必须多加小心了。 



取用第4章中例子的简化版本,找出订购蝙蝠车的客户,典型实现如下: 

select distinct orders。custid 

from orders 

join orderdetail 

on (orderdetail。ordid =orders。ordid) 

join articles 

on (articles。artid=orderdetail。artid) 

where articles。artname ='BATMOBILE' 

依我看,明确使用子查询来检查客户订单是否包含某项商品,才是较好的方式,而且也比较容 

易理解。但应该采用“关联子查询”还是“非关联子查询”呢?由于我们没有其他条件,所以答案 


…………………………………………………………Page 57……………………………………………………………

应该很清楚:非关联子查询。否则,就必须扫描orders表,并针对每条记录执行子查询——当orders 

表规模小时通常不会查觉其中问题,但随着orders表越来越大,它的性能就逐渐让我们如坐针毡 

了。 



非关联子查询可以用如下的经典风格编写: 

select distinct orders。custid 

from orders 

where ordid in(select orderdetails。ordid 

from orderdetail 

join articles 

on (articles。artid=orderdetail。artid) 

where articles。artname ='BATMOBILE') 

或采用from子句中的子查询: 

select distinct orders。custid 

from orders; 

(select orderdetails。ordid 

from orderdetail 

join articles 

on (articles。artid=orderdetail。artid) 

where articles。artname ='BATMOBILE') assub_q 

where sub_q。ordid =orders。ordid 



我认为第一个查询较为易读,当然这取决于个人喜好。别忘了,在子查询结果上的 in() 条件暗 

含了distinct处理,会引起排序,而排序把我们带到了关系模型的边缘。 



总结:如果要使用子查询,在选择关联子查询、还是非关联子查询的问题上,应仔细考虑。 



多个宽泛条件的交集 



Small Intersection of BroadCriteria 



本节讨论对多个宽泛条件取交集获得较小结果集的情况。在分别使用各个条件时,会产生大型 

数据集,但最终各个大型数据集的交集却是小结果集。 



继续上一节的例子。如果“判断订购的商品是否存在”可选择性较差,就必须考虑其他条件(否 

则结果集就不是小结果集)。在这种情况下,使用正规连接、关联子查询,还是非关联子查询, 

要根据不同条件的过滤能力和已存在哪些索引而定。 

例如,由于不太畅销,我们不再检索订购蝙蝠车的人,而是查找上周六购买某种肥皂的客户。 

此时,我们的查询语句为: 



select distinct orders。custid 

from orders 

join orderdetail 


…………………………………………………………Page 58……………………………………………………………

on (orderdetail。ordid =orders。ordid) 

join articles 

on (articles。artid=orderdetail。artid) 

where articles。artname ='SOAP' 

and 

这个处理流程很合逻辑,该逻辑和商品具有高可选择性时相反:先取得商品,再取得包含商品 

的明细订单,最后处理订单。对目前讨论的肥皂订单的情况而言,我们应该先取得在较短期间 

内下的少量订单,再检查哪些订单涉及肥皂。从实践角度来看,我们将使用完全不同的索引: 

第一个例子需要orderdetail表的商品名称、商品ID这两个字段上的索引,以及orders表的主键 

orderid上的索引;而此肥皂订单的例子需要orders表日期字段的索引、orderdetail表的订单ID字 

段的索引,以及articles表的主键orderid上的索引。当然,我们首先假设索引对上述两例都是最 

佳方式。 



要知道哪些客户在上星期六买了肥皂,最明显而自然的选择是使用关联子查询: 



select distinct orders。custid 

from orders 

where 

andexists (select 1 

from orderdetail 

join articles 

on (articles。artid=orderdetail。artid) 

where articles。artname ='SOAP' 

andorderdetails。ordid =orders。ordid) 

在这个方法中,为了使关联子查询速度较快,需要orderdetail表的 ordid字段上有索引(就可以 

通过主键artid取得商品,无需其他索引)。 



第3章已提到,事务处理型数据库(transactional database)的索引是种奢侈,因为它处在经常更 

改的环境中,维护的成本很高。于是选择“次佳”解决方案:当表orderdetail 上的索引并不重要, 

而且也有充足理由不再另建索引时,我们考虑以下方式: 



select distinct orders。custid 

from orders; 

(select orderdetails。ordid 

from orderdetail; 

articles 



where articles。artid=orderdetail。artid 

andarticles。artname ='SOAP') assub_q 

where sub_q。ordid =orders。ordid 

and 


…………………………………………………………Page 59……………………………………………………………

这第二个方法对索引的要求有所不同:如果商品数量不超过数百万项,即使artname字段上没有 

索引,基于商品名称条件的查询性能也不错。表orderdetail的artid字段可能也不需索引:如果商 

品很畅销,出现在许多订单中,则表orderdetail和articles之间的连接通过哈希或合并连接(merge 

join)更高效,而artid字段上的索引会引起嵌套的循环。与第一种方法相比,第二种方法属于索 

引较少的解决方案。一方面,我们无法承受为表的每个字段建立索引;另一方面,应用中都有 

一些“次要的”查询,它们不太重要,对响应时间要求也不苛刻,索引较少的解决方案完全满足 

它们的要求。 



总结:为现存的查询增加搜索条件,可能彻底改变先前的构想:修改过的查询成了新查询。 



多个间接宽泛条件的交集 



Small Intersection; Indirect BroadCriteria 



为了构造查询条件,需要连接(join)源表之外的表,并在条件中使用该表的字段,就叫间接条 

件(indirect criterion)。正如上一节“多个宽泛条件的交集”的情况,通过两个或多个宽泛条件的 

交集处理获取小结果集,是项艰难的工作;若是涉及多次join操作,或者对中心表(centraltable) 

进行join操作,则会更加困难——这是典型的“星形schema(starschema)”(第10章详细讨论), 

实际的数据库系统中经常遇到。对于多个可选择性差的条�
返回目录 上一页 下一页 回到顶部 赞(1) 踩(1)
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!