2016-01-14
子查询
出现在FROM、WHERE、HAVING子句中的SELECT语句。
一、单行子查询
--对外部SQL不返回结果,或只返回一行。
1.WHERE子句(嵌套子查询 inline view)
select first_name, last_name from customers where customer_id = (select customer_id from customers where last_name = 'Brown'); select product_id, name, price from products where price > (select avg(price) from products);
2.HAVING子句
select product_type_id, avg(price) from products group by product_type_id having avg(price) < (select max(avg(price)) from products group by product_type_id) order by product_type_id;
3.FROM子句(内联视图 nested subquery)
select product_id from (select product_id from products where product_id < 3); select prds.product_id, price, purchase_data.product_count from products prds, (select product_id, count(product_id) product_count from purchases group by product_id) purchases_data where prds.product_id = purchases_data.product_id;
二、多行子查询
--向外部SQL返回一行或多行。
1.IN关键字
select product_id, name from products where product_id in (1, 2, 3); select product_id, name from products where product_id in (select product_id from products where name like '%e%'); select product_id, name from products where product_id not in (select product_id from purchases);
2.ANY关键字
select employee_id, last_name from employees where salary < any (select low_salary from salary_grades) order by employee_id;
3.ALL关键字
select employee_id, last_name from employees where salary > all (select high_salary from salary_grades);
三、多列子查询
--向外部SQL返回多列。
select product_id, product_type_id, name, price from products where (product_type_id, price) in (select product_type_id, min(price) from products group by product_type_id) order by product_id;
四、关联子查询
--引用外部SQL的一列或多列。
--外部查询的每一行都被逐行传递给子查询,直到外部查询中所有行都被处理完,然后返回整个查询结果。
select product_id, product_type_id, name, price from products outer_tb where price > (select avg(price) from products inner_tb where inner_tb.product_type_id = outer_tb.product_type_id) order by product_id;
1.EXISTS关键字
select employee_id, last_name from employees outer_tb where exists (select employee_id from employees inner_tb where inner_tb.manager_id = outer_tb.employee_id) order by employee_id; select employee_id, last_name from employees outer_tb where exists (select 1 from employees inner_tb where inner_tb.manager_id = outer_tb.employee_id) order by employee_id;
2.NOT EXISTS关键字
select product_id, name from products outer_tb where not exists (select 1 from purchases inner_tb where inner_tb.product_id = outer_tb.product_id) order by product_id;
3.EXISTS、NOT EXISTS、IN、NOT IN
--EXISTS性能比IN高,尽可能使用EXISTS,而不是IN --当值列表包含空值,NOT EXISTS返回true,NOT IN返回false --子查询返回行包含空值,NOT EXISTS操作符返回false select product_type_id, name from product_types outer_tb where not exists (select 1 from products inner_tb where inner_tb.product_type_id = outer_tb.product_type_id) order by product_type_id; --子查询返回行包含空值,NOT IN操作符返回false select product_type_id, name from product_types where product_type_id not in (select product_type_id from products) order by product_type_id; select product_type_id, name from product_types where product_type_id not in (select nvl(product_type_id, 0) from products) order by product_type_id;
五、嵌套子查询
--出现在WHERE子句的SELECT select product_type_id, avg(price) from products group by product_type_id having avg(price) < (select max(avg(price)) from products where product_type_id in (select product_type_id from purchases where quantity > 1) group by product_type_id) order by product_type_id;
六、UPDATE、DELETE子查询
1.UPDATE语句
update employees set salary = (select avg(high_salary) from salary_grades) where employee_id = 4);
2.DELETE语句
delete from employees where salary > (select avg(high_salary) from salary_grades);
七、WITH语句
with customer_purchases as (select cu.customer_id, sum(pr.price * pu.quantity) as purchase_total from customers cu, purchases pu, products pr where cu.cusotmer_id = pr.product_id group by cu.customer_id) select * from customer_purchases order by customer_id; with customer_purchases as (select cu.customer_id, sum(pr.price * pu.quantity) as purchase_total from customers cu, purchases pu, products pr where cu.cusotmer_id = pr.product_id and pu.product_id = pr.product_id group by cu.customer_id), average_purchase as (select sum(purchase_total) / count(*) as average from customer_purchases) select * from customer_purchases where purchase_total < (select average from average_purchase) order by customer_id;
【参考资料】
[1] Jason Price.精通Oracle Database 12c SQL&PLSQL编程(第3版).[M].北京:清华大学出版社,2014