SQL多表查询
1、集合理论
1.1 什么是集合
具有某种特定性质的事物的总体。
集合的特性:无序性、互异性、确定性。
一个集合可以小到从一个表中取出一行中的一列。 1 rows 1 cols
也可以不返回任何行--空集 0 rows n cols
也可以有多个列,这些列可以是从多个表中取出的多行信息。 m rows n cols
结果集中的每一行就是这个集合的一个元素。
1.2集合运算
1)交
用来得到两个或多个不同集合的共同元素。
A ∩ B = {e∈A 且 e∈B}
2)减
用来查找在一个集合中出现过,而在另一个集合中没有出现的元素。
A - B = {e|e∈A 且 e!∈B}
3)并
用来合并两个或多个相类似的集合。
A ∪ B = {e∈A 或 e∈B}
1.3 交
INTERSECT
Intersect
SELECT p.product_id,p.product_type_id,p.name
FROM products p
intersect
SELECT m.prd_id,m.prd_type_id,m.name
FROM more_products m
同时在A,B表中出现
4.4差
MINUS
SELECT p.product_id,p.product_type_id,p.name
FROM products p
minus
SELECT m.prd_id,m.prd_type_id,m.name
FROM more_products m
在A表中存在,而在B表中不存在的数据
select a.*,rownum from
(select * from employees2 e order by e.salary desc) a where rownum <=10
minus
select a.*,rownum from
(select * from employees2 e order by e.salary desc) a where rownum <=2
4.5并
--使用union all操作符
--union all操作符返回查询所检索出的所有行,包括重复行。
SELECT p.product_id,p.product_type_id,p.name
FROM products p
union all
SELECT m.prd_id,m.prd_type_id,m.name
FROM more_products m
select * from products
select * from more_products
--union all中间不能包含order by子句
SELECT product_id,product_type_id,NAME
FROM products
--ORDER BY 1 DESC
UNION ALL
SELECT prd_id,prd_type_id,NAME
FROM more_products
ORDER BY 1 DESC;
--使用union操作符
--union操作符返回查询检索出的所有非重复行
SELECT product_id,product_type_id,NAME
FROM products
UNION
SELECT prd_id,prd_type_id,NAME
FROM more_products
ORDER BY 1 DESC;
课堂笔记
select p.product_id,p.product_type_id,p.name from products p;
select mp.prd_id,mp.prd_type_id,mp.name from more_products mp;
----交集
select p.product_id,p.product_type_id,p.name from products p
intersect
select mp.prd_id,mp.prd_type_id,mp.name from more_products mp;
----查询出被购买㢧的产品,并且价格低于20元的产品id
select p.product_id from products p where p.price<20
intersect
select distinct pr.product_id from purchases pr;
--多表查询
select distinct p.product_id from products p,purchases pr where
p.product_id=pr.product_id and p.price<20;
--in 方法
select p.product_id from products p where p.price <20 and
p.product_id in (select distinct pr.product_id from purchases pr);
------并集 union
select p.product_id,p.product_type_id,p.name from products p
union all
select mp.prd_id,mp.prd_type_id,mp.name from more_products mp;
---查询出工资最高与工资最低的员工的信息
select * from
(select * from employees2 e order by e.salary desc) where rownum=1
union
select * from
(select * from employees2 e order by e.salary) where rownum=1;
---减集 minus
select p.product_id,p.product_type_id,p.name from products p
minus
select mp.prd_id,mp.prd_type_id,mp.name from more_products mp;
--------------------按照工资排序,查询出第六名到第十名的员工信息
select * from
(select * from employees2 e order by e.salary desc)
where rownum<=10
minus
select * from
(select * from employees2 e order by e.salary desc)
where rownum<=5
---查询出产品的id号,产品的名字,产品的价格,产品类型名。
select * from products;
select * from product_types;
select p.product_id,p.name,p.price,pt.name from products p,product_types pt
where p.product_type_id = pt.product_type_id
union
select p.product_id,p.name,p.price,null
from products p where p.product_type_id is null;
2 内连接
2.1什么是连接
将数据库中的两个或多个表组合起来。把不同表的数据通过条件连接在一起。
把多个表联合或者连接起来才能得到想要的结果。
在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。
当检索数据时,通过连接操作查询出存放在多个表中的不同实体的信息。
连接操作给用户带来很大的灵活性,他们可以在任何时候增加新的数据类型。
为不同实体创建新的表,尔后通过连接进行查询。
连接在SQL92标准中用join关键字来实现,JOIN 关键字操作本质上来说
也是一种集合的交运算,它可以指定一些列,系统只要求这些列匹配,
从而完成集合的连接。
在一个SQL语句中,JOIN 作为 FROM 子句的一部分。
JOIN 定义了一个逻辑表,它是两个表或结果集连接后的结果。
2.2连接类型
SQL-92标准所定义的FROM子句的连接语法格式为:
FROM join_table join_type join_table
[ON (join_condition)]
--join_table
其中join_table指出参与连接操作的表名,连接可以对同一个表操作,
也可以对多表操作,对同一个表操作的连接又称做自连接。
--join_type
join_type 指出连接类型,可分为三种:内连接、外连接和交叉连接。
1)内连接(INNER JOIN)
使用比较运算符进行表间某(些)列数据的比较操作,
并列出这些表中与连接条件相匹配的数据行。
根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种。
2)外连接(OUTER JOIN)
与内连接不同的是,外连接不只列出与连接条件相匹配的行,
而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行。
外连接分:
左外连接(LEFT OUTER JOIN 或 LEFT JOIN)、
右外连接(RIGHT OUTER JOIN 或 RIGHT JOIN)和
全外连接(FULL OUTER JOIN 或 FULL JOIN)三种。
3)交叉连接(CROSS JOIN)
返回连接表中所有数据行的笛卡尔积。
(若表A有m行,表B有n行,则交叉连接后的结果集有:m*n 行)
对SQL92标准来说,交叉连接(CROSS JOIN)不能使用有 ON 或 USING 关键字;
对于SQL89标准来说,就是不带where搜索条件的连接。
--SQL89语法
S product_types;
SELECT * FROM products, product_types;
--join_condition
连接操作中的ON (join_condition) 子句指出连接条件,
它由被连接表中的列和比较运算符、逻辑运算符等构成。
若两个表的连接列列名相同,则可以简写为:
USING(column_name)
--查询出产品的名,产品类型名,产品价格
select p.product_type_id,p.name pro_name,
(select pt.name from product_types pt where pt.product_type_id=p.product_type_id) type_name,p.price
from products p;
2.3内连接
1)定义及类型
只返回那些同时和两个表或结果集匹配的数据行。
内连接基于连接谓词将两张表(如 A 和 B)的列组合在一起,产生新的结果表。
查询会将 A 表的每一行和 B 表的每一行进行比较,并找出满足连接谓词的组合。
当连接谓词被满足,A 和 B 中匹配的行会按列组合(并排组合)成结果集中的一行。
连接产生的结果集,可以定义为首先对两张表做笛卡尔积(交叉连接),
即将 A 中的每一行和 B 中的每一行组合,然后返回满足连接谓词的记录。
内连接分三种:
(1)等值连接:
在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复列。
(2)不等连接:
在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些运算符包括>、>=、<=、<、<>。
(3)自然连接:
在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。
2)语法
SELECT value_expression
FROM table_name
INNER JOIN table_name
ON search_condition;
OR
SELECT value_expression
FROM table_name
INNER JOIN table_name
USING(column_name);
--SQL89语法
SELECT value_expression
FROM table_name, table_name
WHERE search_condition;
写一条sql语句
查询出产品名字,产品类型名,产品价格?
如同可以在 WHERE 子句中使用搜索条件一样,在 ON 子句中也可以使用搜索条件。
SELECT * FROM products;
SELECT * FROM product_types;
SELECT products.*,product_types.*
FROM products
inner join product_types
on products.product_type_id = product_types.product_type_id;
SELECT products.name, product_types.name
FROM products
inner join product_types
on products.product_type_id = product_types.product_type_id;
3)等值连接
ON 子句中搜索条件为 = 比较操作符
SELECT * FROM products;
SELECT * FROM purchases;
SELECT *
FROM products pd
INNER JOIN purchases pc
ON pd.product_id = pc.product_id;
4)不等连接
ON 子句中的搜索条件为 <> > >= < <= 比较操作符
SELECT * FROM products;
SELECT * FROM product_types;
SELECT products.*,product_types.*
FROM products
inner join product_types
on nvl(products.product_type_id,2) <> product_types.product_type_id;
5) NATURAL INNER JOIN
连接的表中有相同的列名(一个或多个),系统默认使用这些同名的列作为相等连接条件。
value_expression中不能使用表别名。
SELECT * FROM products;
SELECT * FROM purchases;
SELECT customer_id, product_id, price, quantity
FROM purchases natural inner join products;
相当于
select a.product_id,b.customer_id,a.price,b.quantity
from products a inner join purchases b on a.product_id = b.product_id
6)表别名
可以对连接的表加一个别名,注意与列别名的区别,不能加 AS 。
SELECT p.name, pt.name
FROM products P
INNER JOIN product_types pt
ON p.product_type_id = pt.product_type_id;
7)SELECT 语句嵌套
SELECT value_expression
FROM (select_statement)
INNER JOIN (select_statement)
ON search_condition;
OR
SELECT value_expression
FROM (select_statement)
INNER JOIN (select_statement)
USING(column_name);
--查询出产品价格大于15元并且被购买数量超过1个的产品。
SELECT * FROM products;
SELECT * FROM purchases;
SELECT product_id, name, price
FROM products
WHERE product_type_id IS NOT NULL
AND price > 15
SELECT product_id, customer_id, quantity
FROM purchases
WHERE quantity > 1
SELECT pd.product_id, pd.name, pc.customer_id, pc.quantity
FROM (SELECT product_id, name, price
FROM products
WHERE product_type_id IS NOT NULL
AND price > 15) pd
INNER JOIN (SELECT product_id, customer_id, quantity
FROM purchases
WHERE quantity > 1) pc
ON pc.product_id = pd.product_id;
--查询出产品价格大于15元并且被购买数量超过1个的产品。
SELECT * FROM products;
SELECT * FROM purchases;
select p.product_id,p.name from products p inner join purchases pr on p.product_id=pr.product_id
where pr.quantity>1 and p.price >15;
select a.product_id,a.name from
(select * from products p where p.price>15) a inner join
(select * from purchases pr where pr.quantity>1) b on a.product_id=b.product_id;
select p.product_id,p.name from products p where p.price>15 and p.product_id
in(select pr.product_id from purchases pr where pr.quantity>1);
select p.product_id,p.name from products p where p.product_id in
(select p.product_id from products p where p.price>15
intersect
select pr.product_id from purchases pr where pr.quantity>1);
8)JOIN 和 JOIN 嵌套
SELECT value_expression
FROM (table_name INNER JOIN table_name ON search_condition)
INNER JOIN
table_name
ON search_condition;
SELECT
SELECT value_expression
FROM table_name
INNER JOIN
(table_name INNER JOIN table_name ON search_condition)
ON searcha_condition;
select * from orders;
select * from customers c;
select * from employees e;
--查询出订单号小于100,下订单的客户名与处理订单的雇员名
select a.ordernumber,a.custfirstname,a.custlastname,e.empfirstname,e.emplastname from
(select * from orders o inner join customers c on o.customerid=c.customerid) a
inner join employees e on a.employeeid = e.employeeid where a.ordernumber<100;
select o.ordernumber,c.custfirstname,c.custlastname,e.empfirstname,e.emplastname
from (orders o inner join customers c on o.customerid=c.customerid)
inner join employees e on o.employeeid=e.employeeid where o.ordernumber<100;
select o.ordernumber,c.custfirstname,c.custlastname,e.empfirstname,e.emplastname
from (orders o inner join customers c on o.customerid=c.customerid and o.ordernumber<100)
inner join employees e on o.employeeid=e.employeeid;
3 外连接
3.1什么是外连接
返回的不仅和所指定的判断标准匹配的行信息,同时也需要把连接体中不匹配的信息返回。
OUTER JOIN 也用于计算两个集合的差值。
内连接时,返回查询结果集合中的仅是符合连接条件的行。
而采用外连接时,它返回到查询结果集合中的不仅包含符合连接条件的行,
而且还包括左表(左外连接时)、右表(右外连接时)或两个连接表(全外连接)中的所有数据行。
1)左外连接:
左外连接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。
如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表的列值均为空值。
2)右外连接:
右外连接是左外连接的反向联接。将返回右表的所有行。
如果右表的某行在左表中没有匹配行,则将为左表的列表值返回空值。
3)完整外连接:
完整外连接返回左表和右表中的所有行。
当某行在另一个表中没有匹配行时,则另一个表的选择列表列值包含空值。
如果表之间有匹配行,则整个结果集行包含基表的数据值。
3.2左/右外连接
1)定义
获取一个表或结果集中所有行以及另一个表或结果集中所有匹配的行
出现在 JOIN 前的第一个表为左表,JOIN 后的第二个表为右表
理解:
左外连接:先对A表和B表做内连接,再将A表没有匹配的行加入到结果集中得到最终的结果集。
右外连接:先对A表和B表做内连接,再将B表没有匹配的行加入到结果集中得到最终的结果集。
2)语法
SELECT value_expression
FROM table_name
LEFT OUTER JOIN
table_name
ON search_condition;
SELECT value_expression
FROM table_name
RIGHT OUTER JOIN
table_name
ON search_condition;
--SQL89语法
--左外连接
SELECT value_expression
FROM left_table, right_table
WHERE left_table.column = right_table.column(+);
--右外连接
SELECT value_expression
FROM left_table, right_table
WHERE left_table.column(+) = right_table.column;
3)左外连接
1、
SELECT * FROM products;
SELECT * FROM product_types;
预置条件
update products set products.product_type_id='' where products.product_id=11;
insert into product_types values(6,'evd');
select * from products p inner join product_types pt on p.product_type_id =pt.product_type_id;
select * from products p left outer join product_types pt on p.product_type_id =pt.product_type_id;
2、
SELECT * FROM products;
SELECT * FROM purchases;
SELECT p.product_id lpi, p.name lname, pc.quantity rquantity
FROM products p
left OUTER JOIN purchases pc
ON p.product_id = pc.product_id
ORDER BY 1;
3、
SELECT * FROM products;
SELECT * FROM purchases;
SELECT p.product_id lpi, p.name lname, pc.quantity rquantity
FROM products p
left OUTER JOIN purchases pc
ON p.product_id = pc.product_id AND p.product_id <> 1
ORDER BY 1;
4、
SELECT p.product_id lpi, p.name lname, pc.quantity rquantity
FROM products p
LEFT OUTER JOIN purchases pc
ON p.product_id = pc.product_id
WHERE p.product_id <> 1
ORDER BY 1;
查询出没有被购买过的产品的信息
select p.* from (products p left join purchases pr
on p.product_id=pr.product_id) where pr.product_id is null;
4)右外连接
1、
SELECT * FROM products;
SELECT * FROM product_types;
SELECT p.product_id lpi, p.name lname, pt.name rname
FROM products p
RIGHT OUTER JOIN product_types pt
ON p.product_type_id = pt.product_type_id
ORDER BY 1;
2、
SELECT p.product_id lpi, p.name lname, pt.name rname,p.product_type_id,pt.product_type_id
FROM products p
RIGHT OUTER JOIN product_types pt
ON p.product_type_id = pt.product_type_id
AND pt.name <> 'Video'
ORDER BY 1;
5)SELECT 语句嵌套
SELECT value_expression
FROM (select_statement)
OUTER LEFT/RIGHT JOIN
(select_statement)
ON search_condition;
1、
SELECT * FROM products;
SELECT * FROM purchases;
SELECT pd.product_id, pd.name, pd.name, pc.customer_id, pc.quantity
FROM (SELECT product_id, name, price
FROM products
WHERE product_type_id IS NOT NULL
AND price > 15) pd
LEFT OUTER JOIN (SELECT product_id, customer_id, quantity
FROM purchases
WHERE quantity > 1) pc
ON pc.product_id = pd.product_id;
2、
SELECT * FROM products;
SELECT * FROM product_types;
SELECT pd.product_id,pd.product_type_id, pd.name, pd.name,pt.product_type_id, pt.name
FROM (SELECT product_id, product_type_id, name, price
FROM products
WHERE price > 15) pd
RIGHT OUTER JOIN (SELECT product_type_id, NAME
FROM product_types
WHERE product_type_id <> 1) pt
ON pd.product_type_id = pt.product_type_id;
--哪些用户没有购买过Supernova产品(select嵌套)
SELECT * FROM customers;
SELECT * FROM products;
SELECT * FROM purchases;
--购买过Supernova 的顾客id
select pr.customer_id from products p inner join purchases pr on p.product_id=pr.product_id and p.name='Supernova';
没有购买过Supernova产品的顾客
select * from customers c where c.customer_id not in
(select pr.customer_id from products p inner join purchases pr on p.product_id=pr.product_id and p.name ='Supernova')
另一种写法
select c.customer_id,c.first_name,c.last_name,pp.product_id from customers c left outer join
(select p.product_id,pc.customer_id from products p inner join purchases pc on p.product_id =pc.product_id and p.name ='Supernova') pp
on c.customer_id = pp.customer_id where pp.product_id is null ;
6)JOIN 和 JOIN 嵌套
SELECT value_expression
FROM (table_name OUTER LEFT/RIGHT JOIN table_name ON search_condition)
LEFT/RIGHT OUTER JOIN
table_name
ON search_condition;
SELECT value_expression
FROM table_name
LEFT/RIGHT OUTER JOIN
(table_name LEFT/RIGHT OUTER JOIN table_name ON search_condition)
ON search_condition;
--哪些用户没有购买过Supernova产品(join嵌套)
SELECT * FROM customers;
SELECT * FROM products;
SELECT * FROM purchases;
select c.customer_id,c.first_name,c.last_name from customers c left outer join(products p inner join purchases pr on p.product_id =pr.product_id and p.name='Supernova')
on c.customer_id =pr.customer_id and p.product_id is null;
3.3完全外连接
1)定义
是左连接和右连接两者的结合
2)语法
SELECT value_expression
FROM table_name FULL OUTER JOIN table_name ON search_condition;
SELECT * FROM products;
SELECT * FROM product_types;
SELECT p.product_id lpi, p.name lname, pt.name rname
FROM products p
FULL OUTER JOIN product_types pt
ON p.product_type_id = pt.product_type_id
ORDER BY 1;
总结:
交叉连接->返回符合逻辑表达式的行(内连接)->加入左表不符合逻辑表达式的行(左外连接)
交叉连接->返回符合逻辑表达式的行(内连接)->加入右表不符合逻辑表达式的行(右外连接)
交叉连接->返回符合逻辑表达式的行(内连接)->加入右表不符合逻辑表达式的行(右外连接)->加入左表不符合逻辑表达式的行(左外连接)->返回结果集(全外连接)
4 子查询
4.1什么是子查询
1)定义
子查询就是一个select表达式,这个表达式被嵌入select语句的一个子句中,
组成最终的查询语句。
SQL标准中定义了三种不同类型的子查询:
(1)行子查询(ROW subquery)
一个嵌入的select表达式,返回多个列以及返回的行数不超过1。 n cols 0/1 rows
(2)表子查询(TABLE subquery)
一个嵌入的select表达式,返回单个或多个列,行数任意。 n cols m rows
(3)标量子查询(scalar subquery)
一个嵌入的select表达式,返回单行单列值。 1 cols 1 rows
2)行子查询
SQL标准中规定了一个行值构造函数可以作为where、having或on子句中查询条件谓词的一部分。
oracle不支持。
比如:
SELECT * FROM products;
SELECT * FROM products
WHERE (product_id, price) > (1, 20);
4.2作为列表达式的子查询
1)句法
SELECT value_expression FROM table_name;
value_expression:
操作数:
Literal_VALUE
COLUMN_REFERENCE
FUNCTION
(select_expression)
(value_expression)
操作符:
+
-
*
/
||
2)例子
SELECT * FROM customers;
SELECT * FROM products;
SELECT * FROM purchases;
--在select子句列表中
SELECT c.first_name,
c.last_name,
( SELECT COUNT(*) FROM purchases p,customers c WHERE p.customer_id = c.customer_id ) pchcnt
FROM customers c;
与下面的语句是不一样的。
SELECT c.first_name,
c.last_name,
(SELECT COUNT(*) FROM purchases p WHERE p.customer_id = c.customer_id) pchcnt
FROM customers c;
上面的语句,c.customer_id 是customer表中查询的值,一一匹配
而下面的语句,内部的customer表与外部的customer表不是一个概念。
--产品id,产品名字,产品类型名,产品价格
select p.product_id,p.name,
(select pt.name from product_types pt where pt.product_type_id=p.product_type_id) type_name,
p.price from products p;
--在where搜索条件中
SELECT * FROM products;
SELECT * FROM purchases;
被购买的产品ID有
select distinct ps.product_id from purchases ps
写出被购买过的产品的名字与价格
SELECT p.product_id, p.name, p.price
FROM products p
WHERE p.product_id in
(select distinct ps.product_id from purchases ps);
三表查询
select c.first_name,p.name,p.price from products p inner join purchases pu
on p.product_id = pu.product_id
inner join customers c on c.customer_id = pu.customer_id
4.3作为过滤器的子查询
1)句法
SELECT value_expression
FROM table_reference
WHERE search_condition
GROUP BY value_expression
HAVING search_condition
其中
table_reference包括 ON search_condition
WHERE search_condition
HAVING search_condition中都可以使用子查询。
2)子查询的特定谓词关键字
(1)集合成员 IN /NOT IN
SELECT value_expression
FROM table_reference
WHERE value_expression [NOT] IN (select_expression)/(value_expression);
SELECT * FROM products;
SELECT * FROM purchases;
被购买过的产品信息
SELECT *
FROM products
WHERE product_id IN (SELECT product_id FROM purchases);
没被购买过产品的信息
SELECT *
FROM products
WHERE product_id NOT IN (SELECT product_id FROM purchases);
SELECT *
FROM products
WHERE (product_id, product_type_id) IN
(SELECT product_id, quantity FROM purchases);
(2)定量比较谓词 ALL ANY
ANY = SOME
SELECT value_expression
FROM table_reference
WHERE value_expression =/<>/</<=/>/>= ALL/ANY/SOME (select_expression);
SELECT *
FROM products
WHERE product_id = ANY (SELECT product_id FROM purchases);
SELECT *
FROM products
WHERE product_id > ANY (SELECT product_id FROM purchases);
大于any :大于最小的,
小于any :小于最大的
SELECT *
FROM products
WHERE product_id > ALL (SELECT product_id FROM purchases);
小于all ,小于最小的
大于all,大于最大的
--查询出工资低于各部门平均工资的员工
select * from employees2 e where e.salary <all(
select avg(e.salary) from employees2 e group by e.division_id);
select * from employees2 e where e.salary <
(select min(avg(e.salary)) from employees2 e group by e.division_id)
(3)存在谓词 EXISTS / NOT EXISTS
EXISTS谓词只注重子查询是否返回行。如果子查询返回一个或多个行,谓词返回为true,否则返回false。
EXISTS搜索条件并不真正地使用子查询的结果。它仅仅测试子查询是否产生任何结果。
可以使用 NOT EXISTS 形式颠倒 EXISTS 测试的逻辑。
在此情况下,如果子查询没有生成任何行,则该测试返回 true,否则返回 false。
SELECT * FROM products;
SELECT * FROM purchases;
SELECT *
FROM products p
WHERE EXISTS
(SELECT * FROM purchases pc,products p WHERE p.product_id = pc.product_id);
SELECT *
FROM products p
WHERE NOT EXISTS
(SELECT * FROM purchases pc WHERE p.product_id = pc.product_id);
select p.product_id,p.name,p.price from products p where exists
(select * from purchases pr where pr.product_id =p.product_id and pr.quantity>1)
关联子查询
SELECT * FROM products;
SELECT * FROM purchases;
--exists 与 not exists 谓词
select * from products where not exists (select * from purchases);
---查询出没有被购买过的产品信息
--1 not in
select * from products p where p.product_id not in
(select distinct pr.product_id from purchases pr);
--2 左外连接
select p.* from products p left join purchases pr
on p.product_id = pr.product_id where pr.product_id is null;
--3 exists 子查询
select * from products p where not exists (select * from purchases pr where pr.product_id =p.product_id);
子查询可包含对父语句中所定义对象的引用。这称为外部引用。包含外部引用的子查询称为相关子查询。
相关子查询无法独立于外部查询进行计算,因为子查询使用了父语句的值。
即,会针对父语句中的每一行来执行子查询。因此,子查询的结果取决于父语句中正在计算的活动行。
多表查询
雇员表与部门表
select * from employees2 e,divisions d where e.division_id = d.division_id
select e.employee_id,division_id,e.first_name from employees2 e,divisions d
where e.division_id = d.division_id 为什么会报错
select e.employee_id,e.division_id,d.division_id,e.first_name from employees2 e,divisions d where e.division_id = d.division_id
三表
cselect * from employees2 e,divisions d,jobs j where e.division_id = d.division_id and e.job_id = j.job_id
--课堂练习
1)山地车的平均零售价格是多少?(Bikes)
2)最近一次订货的日期是哪一天?
3)第8号订单的订货总额是多少?
4)列出每一个供应商名字以及每一个供应商的平均发货天数;
5)列出每一个供应商,并且当其平均发货天数大于所有供应商平均发货天数时列出其平均发货天数;
6)列出每一种产品的产品名和总销售额;
--5)列出每一种产品的产品名和总销售额;
--6)列出每一类产品的产品类别名和总销售额;
--7)列出每一个订单的订单号和总销售额;
8)有多少次订购只定了一种产品?
--1
select c.categorydescription,avg(p.retailprice)
from products p,categories c
where p.categoryid =c.categoryid and c.categoryid =2
group by c.categorydescription;
--2
select a.categorydescription,b.avg_price from categories a,
(select pr.categoryid,avg(pr.retailprice) as avg_price
from products pr group by pr.categoryid having pr.categoryid =2) b
where a.categoryid =2;
select c.categorydescription,
(select avg(p.retailprice) from products p where p.categoryid =2)
from categories c
where c.categoryid =2
查询出工资最多的三个人工资
select a.employee_id,a.salary,rownum from
(select e.employee_id,e.salary from employees2 e order by e.salary desc) a where rownum<=3;
查询出工资第三到第十名的工资
select * from
(select a.employee_id,a.salary,rownum rn from
(select e.employee_id,e.salary from employees2 e order by e.salary desc) a) b where b.rn >=3 and b.rn<=10;
如何从一张表总获取一个随便记录
select pp.*,rownum from
(select p.* from products p order by dbms_random.value) pp where rownum =1;
select * from purchases;
select * from products;
--写出被购买过的产品的名字与价格
select p.name,p.price from products p where p.product_id
in(select distinct pr.product_id from purchases pr);
select distinct p.name,p.price from products p,purchases pr where p.product_id=pr.product_id;
--写出没有被购买过的产品的名字与价格
select p.name,p.price from products p where p.product_id
not in(select distinct pr.product_id from purchases pr);
select p.name,p.price from products p left outer join purchases pr on p.product_id =pr.product_id
where pr.product_id is null;
练习题:
--1 查询出产品的ID号,产品的名字,产品的零售价,产品的类型名。
--2、查询出订单号,下订单的顾客名字,以及处理的雇员的名字。
--3、查询出产品的ID号,供应该产品的供应商的名字,以及该产品的批发价。
--4、查询出产品的名字,供应该产品的供应商的名字,以及该产品的批发价
--5、查询出产品id为8的产品销售总额
--6、查询出产品的ID号,以及每个产品的总销售额。
--6、查询出产品的名字,以及每个产品的总销售额。
--7、查询出销售总额超过2万的产品的名字以及销售额。
--8、查询出每一类产品的类型名,以及每类产品的销售总额。
--9、查询出订单号,以及每个订单号订购了多少种产品
--10、查询订购的产品数超过5个的订单号以及订购的产品种类数。
--11、查询出订购产品种类数超过5个的订单号以及订单总额。
--12、查询出每个雇员的ID号以及每个雇员的销售额
--13 查询出每个雇员的ID号,雇员的名字,以及每个雇员的销售额
--14、查询雇员与顾客住在同一个城市的城市名字、顾客的名字以及雇员的名字。