参考链接
我看的视频为
【中字】SQL进阶教程 | 史上最易懂SQL教程!10小时零基础成长SQL大师!!
这里讲的很好
由于前面的比较简单,我只记录了第三章多表连接,后面如果有时间会更新
第三章 多表连接
3.1 内连接 | Inner Joins (在多张表中查询数据)
handlebars
[INNER] JOIN 内连接
INNER可以省略不写
orders [AS] o / customer [AS] s 表名可以起别名用来下列的简便调用
但是一旦对表名起了别名,其他任何地方都不能再使用原来的表名,而必须使用新的别名
当要查询的列名在多张表都存在时,必须加上 前缀.
语法:
JOIN 表名
ON 连接方法,即找到两者中相同的,多数情况为主键
后面可继续接上JOIN ON语句来连接多张表
mysql
SELECT order_id,c.customer_id,first_name,last_name
FROM orders o
JOIN customers c
ON c.customer_id=o.customer_id;
运行结果

Exercise
handlebars
--Exercise
-- 对照order items表
-- 写一段查询,把这张表和products表连接
-- 每笔订单都返回产品id和名字,连同order items表的数量和单价
mysql
-- Exercise
-- 这里使用oi.unit_price而不是p.unit_price的原因是,
-- products可能会随时改变,而order_price才是下订单时的price
-- product_id也一样
SELECT order_id,oi.product_id,quantity,oi.unit_price
FROM order_items oi
JOIN products p
ON p.product_id=oi.product_id;
运行结果

3.2 跨数据库连接 | Joining Across Databases
handlebars
跨数据库连接表,即连接不在同一数据库下的表
语法:
数据库名.表名
只需在 不在该数据库下的表名前加上前缀
mysql
USE sql_inventory;
SELECT *
FROM sql_store.order_items oi
JOIN products s
ON oi.product_id=s.product_id;
运行结果

3.3 自连接 | Self Joins
handlebars
自连接就是将相同的两张表通过不同的别名,
使用不同的列连接起来,
并通过不同的别名来区分表示列名
mysql
USE sql_hr;
-- 可理解为有第一张员工表,第二张领导表
-- 员工表的reports_to与领导表的employee_id想连接形成一张大表
-- 这里因为id为37270的员工没有reports_to所以第一个表中没有了这一行
-- 由于其余所有的员工reports_to都为37270,所以第二张表中信息全为id 37270
SELECT
e.employee_id,
e.first_name,
m.employee_id AS manager_id,
m.first_name AS manager_first_name
FROM employees e
JOIN employees m
ON e.reports_to=m.employee_id;
运行结果

3.4 多表连接 | Joining Multiple Tables
handlebars
使用JOIN ON进行多表连接
handlebars
USE sql_store;
SELECT
order_id,
order_date,
first_name,
last_name,
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
运行结果 
Exercise
handlebars
1.使用invoicing数据库
2.连接clients,payment_methods,payments三张表
3.查询得到订单日期,订单id,消费金额,顾客名字,支付方式
mysql
USE invoicing;
-- client_id 顾客id
-- invoice_id 订单id
-- status 支付方式
SELECT
p.date,
p.invoice_id,
p.amount,
c.client_id,
c.name AS customer_name,
pm.name AS status
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
运行结果 
3.5 复合连接条件 | Compound Join Conditions
handlebars
当一个表中不能通过一个列来唯一识别时,即这张表的结构为复合主键时
这时我们可以通过 JOIN ON AND 来连接两张表
mysql
USE sql_store;
SELECT *
FROM order_items oi
JOIN order_item_notes oin
ON oi.product_id=oin.product_id
AND oi.order_id=oin.order_id
运行结果 
3.6 隐式连接语法 | Implicit Join Syntax
handlebars
虽然MYSQL中允许使用隐式连接语法,但是为了避免出错,
最好使用显式连接,因为使用显示连接让你不得不注意语法规范
相反地、使用隐式连接可能会漏写WHERE语句
以下是分别通过显式和隐式来进行内连接
mysql
-- 显式连接语句
SELECT *w
FROM customers c
JOIN orders o
ON c.customer_id=o.customer_id;
mysql
-- 隐式连接语句
SELECT *
FROM customers c,orders o
-- 可能会漏写WHERE语句,造成交叉查询的结果
WHERE c.customer_id=o.customer_id;
运行结果

3.7 外连接 | Outer Joins
handlebars
语法:
LEFT/RIGHT [OUTER] JOIN
通过外连接可以实现 ,即使不满足连接条件,也可以实现查询的效果
mysql
-- 左连接
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;
运行结果

mysql
-- 右连接
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;
运行结果 
Exercise
handlebars
-- 写一段查询,实现外连接products和order_items
-- 以实现查询得到含有quantity列为null的product_id
mysql
SELECT
p.product_id,
p.name,
o.quantity
FROM products p
LEFT JOIN order_items o
ON p.product_id=o.product_id
ORDER BY p.product_id;
运行结果 
3.8 多表外连接 | Outer Join Between Multiple Tables
handlebars
多表外连接和多表内连接类似
不同在于返回表中数据的数量不同
最好使用左外连接,避免使用右外连接。
因为当SQL语句数量过多时,如果存在多个连接(包含内外),此时不易辨别表的连接结构
当使用JOIN来连接orders和shippers时
mysql
SELECT
c.customer_id,
c.first_name,
o.order_id
FROM customers c
LEFT JOIN orders o
ON o.customer_id=c.customer_id
JOIN shippers s
ON o.shipper_id=s.shipper_id;
运行结果 
当使用LEFT JOIN来连接orders和shippers时
mysql
SELECT
c.customer_id,
c.first_name,
o.order_id
FROM customers c
LEFT JOIN orders o
ON o.customer_id=c.customer_id
LEFT JOIN shippers s
ON o.shipper_id=s.shipper_id;
运行结果 
Exercise
handlebars
-- 写一段查询实现以下返回结果

mysql
USE sql_store;
SELECT
order_date,
o.order_id,
first_name,
s.name AS shipper,
os.name
FROM orders o
JOIN customers c
ON o.customer_id=c.customer_id
LEFT JOIN shippers s
ON o.shipper_id=s.shipper_id
LEFT JOIN order_statuses os
ON o.status=os.order_status_id
ORDER BY os.name
运行结果 
3.9 自外连接 | Self Outer Jions
handlebars
自外查询和自连接类似
不同在于返回表中数据的数量不同
当使用JOIN来自连接时
mysql
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
运行结果 
当使用LEFT JOIN来自外连接时
mysql
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
运行结果

3.10 USING子句 | The USING Clause
handlebars
USING子句用于替换当连接条件的列名相同时的情况
使用USING子句可以使连接条件更加清楚
USING(列名1...列名n)
mysql
SELECT
o.order_id,
c.first_name,
s.shipper_id AS shipper
FROM customers c
JOIN orders o
-- ON o.customer_id=c.customer_id
USING(customer_id)
LEFT JOIN shippers s
-- ON o.shipper_id=s.shipper_id;
USING(shipper_id)
运行结果 
Exercise
handlebars
-- 写一段查询实现以下返回结果

mysql
SELECT
date,
c.name AS client,
amount,pm.name
FROM payments p
JOIN payment_methods pm
ON p.payment_method=pm.payment_method_id
JOIN clients c
USING(client_id)
运行结果 
3.11 自然连接 | Natural Joins
handlebars
自然连接可以通过表中相同的列名进行连接
但是连接的结果不是可控的
因此在写连接语句时,应尽量避免该语句的出现
mysql
SELECT
o.order_id,
c.first_name
FROM orders o
NATURAL JOIN customers c
运行结果

3.12 交叉连接 | Cross Joins
handlebars
交叉连接是指将两张表的中 每张表的每一列进行映射连接
连接后的表即为两张表自由组合后的表
显式写法
mysql
USE sql_store;
SELECT
c.first_name AS customer,
p.name AS product_name
FROM customers c
CROSS JOIN products p
ORDER BY c.first_name
运行结果 
隐式写法
mysql
SELECT
c.first_name AS customer,
p.name AS product_name
FROM customers c,products p
ORDER BY c.first_name
Exercise
handlebars
-- Do a cross join between shippers and products
-- using the implicit syntax
-- and then using the explicit syntax
使用交叉连接实现连接shippers表和products表
使用隐式写法,然后再使用显式写法
隐式
mysql
SELECT *
FROM shippers,products
ORDER BY product_id
显式
mysql
SELECT *
FROM shippers
CROSS JOIN products
ORDER BY product_id
运行结果 
3.13 联合 | Unions
handlebars
前面的连接都是不同列之间的连接
Union是行的连接,即多个行数据的连接
需要注意的是:
1.进行联合时要注意连接的列数一定要一致
2.联合后返回的列名于第一个查询返回的列名一致
mysql
USE sql_store;
SELECT
order_id,
order_date,
'Active' AS status
FROM orders
WHERE order_date>='2019-01-01'
UNION
SELECT
order_id,
order_date,
'Archive' AS status
FROM orders
WHERE order_date<'2019-01-01';
运行结果 
mysql
SELECT name
FROM shippers
UNION
SELECT first_name
FROM customers
运行结果 
mysql
SELECT first_name
FROM customers
UNION
SELECT name
FROM shippers
运行结果 
Exercise

handlebars
-- 执行一段查询,得到以上的返回结果
-- 新增一个列,名为type,规定:
-- 1.积分小于2000为Bronze(青铜)
-- 2.积分小于等同于3000且大于等于2000为Silver(白银)
-- 3..积分大于3000为Gold(黄金)
-- 注意表中对名字进行了排序
mysql
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>=2000 AND points<=3000
UNION
SELECT
customer_id,
first_name,
points,
'Gold' AS type
FROM customers
WHERE points>3000
ORDER BY first_name;
运行结果
