sql 1030 join

连接

/*
第三章:表的连接
*/

3.1 内连接

use sql_store;
select order_id, o.customer_id, first_name, last_name
from orders o   # 使用缩写
join customers c  # 根据 customer_id 连接
	on o.customer_id = c.customer_id 
order by order_id;


select order_id, oi.product_id, quantity, oi.unit_price
from order_items oi
join products p
	on oi.product_id = p.product_id;

3.2 跨数据库连接

select * 
from order_items oi
join sql_inventory.products p   # 不在current db里的需要加前缀
	on oi.product_id = p.product_id;

## 3.3 自连接 self join
use sql_hr;

select e.employee_id,e.first_name, m.first_name as manager_name
from employees e
join employees m  # 员工之间的从属关系
	on e.reports_to = m.employee_id;

3.4 多表连接

use sql_store;
select 
	o.order_id, 
    o.order_date,
    c.first_name,
    c.last_name,
    os.name as status
from orders o 
join customers c 
	on o.customer_id = c.customer_id
join order_statuses os
	on os.order_status_id = o.status
order by o.order_id;

use invoicing;
select payment_id,date, amount,
	c.name as customer_name,
    pm.name as payment_method
from payments p
join clients c
	on p.client_id = c.client_id
join payment_methods pm
	on pm.payment_method_id = p.payment_method
order by p.date desc;

3.5 复合连接条件

use sql_store;
情况(复合主键):每一个订单有多个产品,需要用订单+产品两列来作为唯一标示(复合主键)
select *
from order_items oi
join order_item_notes oin
	on oi.order_id = oin.order_id
    and oi.product_id = oin.product_id;

3.6 隐式连接

其实就是 全连接/交叉连接 + where条件
最好不要用,还是用Join
select *
from orders o, customers c   
where o.customer_id = c.customer_id;  

3.7 外连接

/*
join:inner join
left / right join :outer join
*/
select   # 这是一个inner join
	c.customer_id,
    c.first_name,
    o.order_id
from customers c
join orders o
	on o.customer_id = c.customer_id
order by c.customer_id;    # 只有部分customers(有order的)


select   # 这是一个outer join
	c.customer_id,
    c.first_name,
    o.order_id
from customers c left join orders o   # c中所有customer都会返回
	on o.customer_id = c.customer_id  # on里的条件只对o起作用
order by c.customer_id;    


select    # 练习
	p.product_id,
    p.name,
    oi.quantity
from products p
left join order_items oi
on p.product_id = oi.product_id;

3.8 多表外连接

多次连接最好只用 left join 方便第三人理解

select   # 这是一个outer join
   c.customer_id,
   c.first_name as customer_name,
   o.order_id,
   o.shipper_id,
   sh.name as shipper_name
from customers c 
left join orders o   
   on o.customer_id = c.customer_id 
left join shippers sh  # 多次外连接
   on sh.shipper_id = o.shipper_id
order by c.customer_id;    

3.9 自外连接

use sql_hr;
select   
	e.employee_id,
    e.first_name,
    m.first_name as manager_name
from employees e
left join employees m   # 老板没有reports_to,leftjoin才能出现
	on e.reports_to = m.employee_id;

3.10 using——简化join

但是只有列名相同之后才能用!

use sql_store;
select 
	o.order_id,
    c.first_name,
    sh.name as shipper_name
from orders o
join customers c
	using (customer_id) 
join shippers sh
	using (shipper_id);


select *  # 前面那个复合主键的问题如何用using
from order_items oi
join order_item_notes oin
	-- on oi.order_id = oin.order_id
    -- and oi.product_id = oin.product_id;
    using (order_id, product_id);
    
    
use invoicing;
select
	p.date,
    c.name as client_name,
    p.amount,
	pm.name as payment_method
from payments p
join clients c 
	using (client_id)
join payment_methods pm
	on pm.payment_method_id = p.payment_method;

3.11 自然连接,自动把相同col作为合并条件

use sql_store;
select
	o.order_id,
    c.first_name
from orders o
natural join customers c; 

3.12 交叉连接

select 
	c.first_name as customer,
	p.name as product
-- from customers c, products p  # 方法1
from customers c
cross join products p   # 方法2. 都不需要条件
order by first_name;

3.13 union 行的combine

select 
	order_id,
    order_date,
    'active' as status
from orders
where order_date >= '2019-01-01'
union   # 行的combine
select 
	order_id,
    order_date,
    'archived' as status
from orders
where order_date < '2019-01-01';

select 
	customer_id,
    first_name,
    points,
    'Gold' as type
from customers
where points > 3000
union
select 
	customer_id,
    first_name,
    points,
    'Silver' as type
from customers
where points <= 3000 and points > 2000
union
select 
	customer_id,
    first_name,
    points,
    'Bronze' as type
from customers
where points <= 2000;