【TechTarget中国原创】SQL中有很多地方可以用到子查询的。本章选自《OCA Oracle Database 11g: SQL Fundamentals I Exam Guide》,将详细阐述如何在SQL中使用子查询,以及子查询所能解决的问题,如星型转换、比较、从SELECT生成表,等等。
下面是一些你可能需要将一个查询的结果作为另一个查询的输入的情况:
用子查询结果集比较
哪些员工的薪水是少于平均薪水值?这问题可以通过两个语句来回答,或者使用一个带子查询的语句。下面是这两种方法的例子:
select avg(salary) from employees; select last_name from employees where salary < result_of_previous_query ; |
另一个就是使用一个带子查询的语句:
select last_name from employees where salary < (select avg(salary)from employees); |
在这个例子中,一个子查询用于替代父查询的WHERE子句的取值:它返回一个值,然后这个值与父查询接收的记录行进行比较。
这个子查询可能返回多行记录。比如,你可以使用下面的语句查找所有拥有一个或多个员工的部门:
select department_name from departments where department_id in (select distinct(department_id) from employees); |
在上一个例子中,子查询替代了连接的使用。相同的结果可以使用下面的语句实现:
select department_name from departments inner join employees on employees.department_id = departments.department_id group by department_name; |
如果子查询能返回多于一行的记录,那么比较操作符必须是可以接受多个值的。这些操作符包括IN、NOT IN、ANY和ALL。如果比较操作符是EQUAL、GREATER_THAN或LESS_THAN(它们只接受单个值),父查询就会出错。
星型转换
用子查询来替代连接操作的一个扩展是使用星型转换,这常用在数据仓库应用中。设想在一个很大的记录销售的表中,每一个卖单都标记为一个买家通过一个特定渠道购买的一个特定的产品。这些属性都通过标记码区分,它们是作为一个相应表的外键使用的,这些表的每一行记录描述了产品、买家和销售渠道。为了确定在德国通过Internet销售一空的所有书本记录,我们可以执行以下的查询:
select … from sales s, products p, buyers b, channels c where s.prod_code=p.prod_code and s.buy_code=b.buy_code and s.chan_code=c.chan_code and p.product='Books' and b.country='Germany' and c.channel='Internet'; |
这个查询使用WHERE子句来连接这些表,然后再过滤结果。下面是一个可以产生相同结果的替代查询:
select … from sales where prod_code in (select prod_code from products where product='Books') and buy_code in (select buy_code from buyers where country='Germany') and chan_code in (select chan_code from channels where channel='Internet); |
这里第一个语句使用了星型转换进行重写。这样写除了使代码变得更有美感(大多数SQL开发者都会有想同审美观点)之外,还有技术原因来说明为什么数据会更有效率地执行修改源查询代码。此外,星型查询也更容易维护;我们可以非常容易地增加一些查询分支或用一列值来替换一些字面值('Books,' 'Germany,' and 'Internet')。