第三章 内连接
13. INNER joins 内连接
目的:从多张列表中选择数据
SELECT *
FROM orders
-- JOIN 关键字,分为INNER JOIN 和外连接,内连接可以不打INNER字样
JOIN customers
ON orders.customer_id = customers.customer_id;
-- 关于结果,前几列是orders里面的,因为先选的是orders表
SELECT order_id, customer_id, first_name, last_name
FROM orders
-- JOIN 关键字,分为INNER JOIN 和外连接,内连接可以不打INNER字样
JOIN customers
ON orders.customer_id = customers.customer_id
-- 会出现错误,因为两张表里都有customer_id, 软件不知道从哪张表里选,所以要加个前缀,orders.customer_id or customer.customer_id
-- 避免重复使用别名
SELECT order_id, o.customer_id, first_name, last_name
FROM orders o -- 空格后为别名
-- JOIN 关键字,分为INNER JOIN 和外连接,内连接可以不打INNER字样
JOIN customers c
ON o.customer_id = c.customer_id
-- exercise 给了一张表,写出相应的代码
SELECT *
FROM order_items oi
JOIN products p ON oi.product_id = p.product_id
-- 一旦一处用了缩写,那么处处都要有缩写
-- exercise 给了一张表,写出相应的代码
SELECT order_id, oi.product_id, quantity, oi.unit_price – 给的答案中判断出要用oi的单位价格
FROM order_items oi
JOIN products p ON oi.product_id = p.product_id
-- 一旦一处用了缩写,那么处处都要有缩写
14. Joining across database 数据库之间的连接
SELECT *
FROM order_items oi
JOIN sql_inventory.products p
ON oi.product_id = p.product_id
# 这个是在 USE sql_store的前提下使用的
15. self join 自连接
USE sql_hr;
select *
FROM employees e
JOIN employees m
ON e.reports_to = m.employee_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
16. Joining multiple tables 多表连接
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
-- 练习
USE sql_invoicing;
SELECT
p.date,
p.invoice_id,
p.amount,
c.name,
pm.name AS method
FROM payments p
JOIN clients c
ON p.client_id = c.client_id
JOIN payment_methods pm
ON p.payment_method = pm.payment_method_id
截图2.jpg
17. Compound join conditions 复合连接条件
之前所有的连接都是用单一列来识别表里的情况
但列里有重复的就无法一一对应的识别
即复合主键
SELECT *
FROM order_items oi
JOIN order_item_notes oin
ON oi.order_id = oin.order_Id
AND oi.product_id = oin.product_id
18. Implicit Join Syntax 隐式连接语法
-- SELECT *
-- FROM orders o
-- JOIN customers c
-- ON o.customer_id = c.customer_id
SELECT *
FROM orders o, customers c
WHERE o.customer_id = c.customer_id
上述两段代码表达的意思是一样的,下面即为隐式连接语法,但如果忘记打WHERE就会出现交叉连接,原来每个表10条记录,会出现100条
19. Outer joins 外连接
Inner joins 的 inner可以省略
SELECT
c.customer_id,
c.first_name,
o.order_id
FROM customers c
JOIN orders o
ON c.customer_id = o.customer_id
ORDER BY c.customer_id
-- 结果集里没有顾客为 1 3等人的信息,要是想看,就用外连接
外连接有两种
LEFT JOIN 和RIGHT JOIN
左连接返回左边表里的所有记录
FROM customers LEFT JOIN orders ,这里的左右指的是join的左右
完整的表达是LEFT OUTER JOIN 但是OUTER 可有可无,像INNER一样
-- 练习
SELECT
p.product_id,
p.name,
oi.quantity
FROM products p
LEFT JOIN order_items oi
ON p.product_id = oi.product_id
20. Outer joins between multiple tables 多表外连接
SELECT
c.customer_id,
c.first_name,
o.order_id,
sh.name AS shipper
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 orders o
LEFT JOIN customers c
ON o.customer_id = c.customer_id
LEFT JOIN shippers sh
ON o.shipper_id = sh.shipper_id
LEFT JOIN order_statuses os
ON o.status = os.order_status_id
-- Mosh答案
SELECT
o.order_date,
o.order_id,
c.first_name AS customer,
sh.name AS shipper,
os.name AS status
FROM orders o
JOIN customers c
ON o.customer_id = c.customer_id
LEFT JOIN shippers sh
ON o.shipper_id = sh.shipper_id
JOIN order_statuses os
ON o.status = os.order_status_id
-- 只用了一个左连接 但答案一样
21. self outer joins 自外连接
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
-- 把管理者也列出来了,虽然他没有管理者,因为管理者就是他自己
22. USING clause USING子句
SELECT
o.order_id,
c.first_name
FROM orders o
JOIN customers c
-- ON o.customer_id = c.customer_id
USING (customer_id)
当两个表中用作连接条件的列名称一样时就可以用这个来简化,内连接和外连接均可用
SELECT *
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)
-----
-- 练习 (invocing数据库)
SELECT
p.date,
c.name AS client,
p.amount,
pm.name AS payment_method
FROM payments p
JOIN clients c
USING (client_id)
JOIN payment_methods pm
ON p.payment_method = pm.payment_method_id
23. Natural joins 自然连接
让引擎自己猜测按照什么来连接,不建议使用
24. Cross Joins 交叉连接
SELECT *
FROM customers c
CROSS JOIN products p
SELECT
c.first_name AS customer,
p.name AS product
FROM customers c(, products p) 隐性语法
-- CROSS JOIN products p 显性语法
ORDER BY c.first_name
--------------------------
-- exercise
-- Do a cross join between shippers and products
-- using the implict syntax
SELECT *
FROM shippers s
CROSS JOIN products p
-- using the explicit syntax
SELECT *
FROM shippers s, products p
25. unions 联合
Joins 将多张表的列连接到一起,那么如何将行连在一起呢?
SELECT
order_id,
order_date,
'Active' AS status
FROM orders
WHERE order_date >= '2019-01-01'
-- 选出当年(2019)的订单,并将其状态标为active
UNION -- 将不同的行连接起来了,可以连接同一个表,也可以连接不同的表
SELECT
order_id,
order_date,
'Acchived' AS status
FROM orders
WHERE order_date < '2019-01-01'
SELECT first_name
FROM customers
UNION
SELECT name
FROM shippers
# 返回的结果的列名称是first_name,如果改变顺序,用shippers那么就会是name
# 两个表的列的数量要一样,否则就会得到错误提示
SELECT first_name, last_name
FROM customers
UNION
SELECT name
FROM shippers
# 这一块就会出错
--------------------------------
-- 练习
SELECT
customer_id,
first_name,
points,
'Bronze' AS type
FROM customers
WHERE points < 2000
UNION
SELECT
customer_id,
first_name,
points,
'Silver' AS type
FROM customers
WHERE points BETWEEN 2000 AND 3000
UNION
SELECT
customer_id,
first_name,
points,
'Gold' AS type
FROM customers
WHERE points > 3000
ORDER BY first_name