相关与不相关的子查询

时间:2016-02-24 03:14:00

标签: sql oracle subquery

我试图弄清楚如何创建一个使用不相关子查询的语句来使用相关子查询来编写它。以下是使用不相关子查询的Oracle SQL:

select 
    Firstname || ', '|| Lastname "Name", title, retail
from 
    Customers 
join 
    orders using (Customer#) 
join 
    orderitems using (Order#)                 
join 
    books using (Isbn)
where 
    (Customer#, retail) in (select Customer#,  max(retail)
                            from books 
                            join orderitems using (isbn) 
                            join Orders using (order#) 
                            join Customers using (Customer#)
                            group by Customer#)                 
order by  
    Firstname, Lastname, title;

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

通常来说,不相关的子查询将比相关的子查询执行得更好。然而,您要求一个相关的子查询,它将提供与您不相关的子查询相同的结果。如果我正确理解了您的查询,那么您正在尝试获取他们购买的最昂贵图书的客户列表(我假设retailbooks上的一列)。

相关子查询:

select Firstname || ', '|| Lastname "Name", title, retail
  from Customers c 
  join orders using (Customer#) 
  join orderitems using (Order#)                 
  join books using (Isbn)
where retail = (
  select max(retail)
    from books b2 
    join orderitems using (isbn) 
    join Orders o using (order#) 
   where o.Customer# = c.Customer#
)                 
order by  Firstname, Lastname, title;

该查询可能比您拥有的查询运行速度慢很多。它实质上将为外部查询的每一行执行内部查询。

如果您正在寻找可以更快速运行的查询,请尝试以下方法:

with order_books as
(
  select Customer#, title, retail
    from orders 
    join orderitems using (Order#)                 
    join books b1 using (Isbn)
)
select Firstname || ', '|| Lastname "Name", ob1.title, ob1.retail
  from Customers
  join order_books ob1 using (Customer#)
  left outer join order_books ob2
    on (   ob2.Customer# = ob1.Customer# 
       and ob2.retail > ob1.retail )
 where ob2.Customer# is null             
 order by  Firstname, Lastname, ob1.title;

此查询不包含子查询,它应该比上述任何一个查询快得多。它使用外部联接查找零售价值高于当前ob2行的ob1行。然后,它使用WHERE子句仅返回不具有任何匹配ob1行的ob2行。

干杯!