3. 查询和连接

108 阅读4分钟

内连接

join默认是自然连接 on表示在什么条件下连接

-- 有重复的customer_id需要确定是哪一个,不然会因为重复而报错
select order_id,orders.customer_id, first_name, last_name 		
from orders
inner join customers 		-- inner可以省略
	on orders.customer_id = customers.customer_id 		

简写表名称

select order_id,a.customer_id, first_name, last_name 
from orders a
inner join customers 		-- inner可以省略
	on a.customer_id = customers.customer_id 		

自然连接 oi 和 p 表中 oi.product_id = p.product_id 的部分,并输出 order_id, oi.product_id, quantity, oi.unit_price

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

跨数据库连接

同理啊,只需要在 join 的表前面加上是哪一个数据库名字就可以。 查询语句会跟着当前使用的数据库的改变而改变

select *
from sql_store.order_items oi
join products p
	on oi.product_id = p.product_id

自连接

use sql_hr;

select 
	e.employee_id,
    e.first_name,
    m.first_name	AS manager
from employees e
join employees m
	on e.reports_to = m.employee_id

和自己链接,通过每个员工编号和领导编号可以输出如下信息。

employee_idfirst_namemanager
33391D'arcyYovonnda
37851SayerYovonnda
40448MindyYovonnda
56274KeriannYovonnda
63196AlasterYovonnda

多表连接

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 o.status = os.order_status_id
82018-06-08ClemmieBetchleyProcessed
62018-11-18LevyMynettProcessed
42017-01-22InesBrushfieldProcessed
32017-12-01ThacherNasebyProcessed
12019-01-30ElkaTwiddellProcessed
use sql_invoicing;

select 
	p.date,
    p.invoice_id,
	c.client_id,
	c.name,
    pm.name
from payments p
join clients c
	on c.client_id = p.client_id
join payment_methods pm
	on pm.payment_method_id = p.payment_method;
2019-02-1225TopicloungeCredit Card
2019-01-0361VinteCredit Card
2019-01-11113YadelCredit Card
2019-01-26135TopicloungeCredit Card
2019-01-15153YadelCredit Card
2019-01-15173YadelCredit Card

复合主键

需要使用多重条件来连接两个主键

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;

隐式链接

隐式链接是上面的显式连接的另一种写法。 但是不推荐这样写,因为一旦忘记写条件,就会得到两张表的积

SELECT *
FROM orders o
JOIN customers c
	ON o.customer_id = c.customer_id;

-- Implpicit Join Syntax
SELECT * 
FROM orders o, customers c
WHERE o.customer_id = c.customer_id

外连接

默认只写join是内连接,只会返回满足 on 条件的记录 如果还想显示未满足的记录,在join前加上left或者right,就是outer外连接

SELECT
	c.customer_id,
    c.first_name,
    o.order_id
FROM customers c
LEFT JOIN orders o
	ON c.customer_id = o.customer_id
ORDER BY c.customer_id

使用LEFT JOIN,customers 中的所有记录都会被返回,不管满不满足条件。 RIGHT JOIN同理。

多表外连接

SELECT
	c.customer_id,
    c.first_name,
    o.order_id,
    sh.name
FROM customers c
LEFT JOIN orders o
	ON c.customer_id = o.customer_id
left Join shippers sh
	on o.shipper_id = sh.shipper_id
ORDER BY c.customer_id

SELECT
	o.order_date,
	o.order_id,
    c.first_name,
    sh.name as shipper,
    os.name as status
FROM customers c
JOIN orders o
	ON c.customer_id = o.customer_id
left Join shippers sh
	on o.shipper_id = sh.shipper_id
Join order_statuses os
	on o.status = os.order_status_id
ORDER BY status
2018-06-088ClemmieProcessed
2018-11-186LevyProcessed
2017-01-224InesProcessed
2017-12-013ThacherProcessed
2019-01-301ElkaProcessed
2018-04-2210ElkaSchinner-PredovicShipped
2017-07-059LevyHettinger LLCShipped
2018-09-227InesMraz, Renner and NolanShipped
2017-08-255ClemmieSatterfield LLCShipped
2018-08-022IleneMraz, Renner and NolanShipped

自外连接

就是对自己使用外连接,可以有不满足条件的地方

use sql_hr;

SELECT
	e.employee_id ,
    e.first_name,
	m.first_name AS manager
FROM employees e
LEFT JOIN employees m
	ON e. reports_to = m. employee_id

USING子句

当作为合并条件(join condition)的列在两个表中有相同的列名时,可用 USING (……, ……) 取代 ON …… AND …… 予以简化,内/外链接均可如此简化。 但是列名不同就必须用 ON

use sql_store;

SELECT
	o.order_id ,
    c.first_name ,
	sh.name AS shipper
FROM orders o
JOIN customers c
	USING(customer_id)
LEFT JOIN shippers sh
	USING (shipper_id)
select *
from order_items oi
left join order_item_notes oin
-- 	on oi.order_id = oin.order_id and
-- 		oi.product_id = oin.product_id
	using (order_id,product_id)

自然连接

就是让MySQL自动检索同名列作为合并条件。 最好别用,因为不确定合并条件是否找对了,有时会造成无法预料的问题,编程时保持对结果的控制是非常重要的

USE sql_store;

SELECT 
    o.order_id,
    c.first_name
FROM orders o
NATURAL JOIN customers c

交叉连接

得到名字和产品的所有组合,因此不需要合并条件显式连接:

select 
	c.first_name,
    p.name
from customers c
cross join products p
order by c.first_name

隐式连接:

select 
	sh.name as shipper,
    p.name as product
from shippers sh,products p
order by sh.name

Union联合

结合多个表的行 FROM …… JOIN …… 可对多张表进行横向列合并,而 …… UNION …… 可用来按行纵向合并多个查询结果,这些查询结果可能来自相同或不同的表

select 
	order_id,
    order_date,
    'Active' as status
from orders
where order_date >= '2019-01-01'
union    -- 联合了上下两个的查询结果
select 
	order_id,
    order_date,
    'Archived' as status
from orders
where order_date < '2019-01-01'
SELECT first_name, last_name
FROM customers
UNION
SELECT nameFROM shippers

注意:

  • 合并的查询结果必须列数相等,否则会报错

  • 合并表里的列名由排在 UNION 前面的决定

select 
	customer_id,
    first_name,
    points,
    'Bronze' as type
from customers
where points < 2000
union
select 
	customer_id,
    first_name,
    points,
    'Sliver' as type
from customers
where points >= 2000 and points < 3000
union
select 
	customer_id,
    first_name,
    points,
    'Gold' as type
from customers
where points >= 3000
order by points desc