字体
第(1/5)页
关灯
   存书签 书架管理 返回目录
    的需求是列出所有尚未标记为完

    成状态的订单(假设所有jiāo易都已终止)的下列字段:订单号、客户名、订单的最后状态,以

    及设置状态的时间。最终,我们写出下列查询,滤掉已完成的订单,并找出订单当前状态:

    乍一看,这个查询很合理,但事实上,它让人非常担心。首先,上面代码中有两个子查询,但

    它们嵌入的方式和前一个例子的方式不同,它们只是彼此间接相关的。最让人担心的是,这两

    个子查询访问相同的表,而且该表在外层已经被访问过。我们编写的过滤条件质量如何呢?因

    为只检查了订单是否完成,所以它不是非常精确。

    这个查询如何执行的呢?很显然,可以扫描orders 表,检查每一条订单记录是否为已完成状

    态——注意,仅通过表orders 即可找出所要信息似乎令人高兴,但实际情况并非如此,因为

    只有上述活动之后,才能检查最新状态的日期,即必须按照子查询编写的顺序来执行。

    上述两个子查询是关联子查询,这很不好。因为必须要扫描orders 表,这意味着我们必须检

    查orders 的每条订单记录状态是否为“COMPLETE”,虽然检查状态的子查询执行很快,但多

    次重复执行就不那么快了。而且,若第一个子查询没找到“COMPLETE” 状态时,还必须执行

    第二个子查询。那么,何不试试非关联子查询呢?

    要编写非关联子查询,最简单的办法是在第二个子查询上做文章。事实上,在某些SQL 方言

    中,我们可以这么写:

    这个子查询会对orderestatus 作“全扫描”,但未必是坏事,下面会对此加以解释。

    重写的子查询条件中,等号左端的“字段对”有点别扭,因为这两个字段来自不同的表,其实不

    必这样。我们想让orders和orderstatus的订单ID相等,但优化器能感知这一点吗?答案是不一

    select c.custncom, o.ordid, os.status, os.statusdate

    from custcomrs c,

    orders o,

    orderstatus os

    where o.ordid = os.ordid

    and not exists (select null

    from orderstatus os2

    where os2.status = 'COMPLETE'

    and os2.ordid = o.ordid)

    and os.statusdate = (select max(statusdate)

    from orderstatus os3

    where os3.ordid = o.ordid)

    and o.custid = c.custid

    and (o.ordid, os.statusdate) = (select ordid, max(statusdate)

    from orderstatus

    group by ordid)

    定。所以优化器可能依然先执行子查询,依然要把orders和orderstatus这两个表连接起来。我

    们应该将查询稍加修改,使优化器更容易明白我
上一章 目录 下一页