表连接
表连接语法
为了解决这个问题,SQL提供表连接语句来实现不同表之间的数据连接,它们由以下的数据库连接语句构成:
表达式 | 含义 |
[INNER] JOIN 表格 ON 连接字段 | 通过两个表格共有的连接字段将两张表进行连接,只会展示两张表都有的公共数据 |
LEFT JOIN 表格 ON 连接字段 | 用于表示按照左边表格作为主表格,完全展示左边的表格数据, 右边的表格有和左边的表格一样的连接字段则展示数据,没有一样的连接字段则省略,数据为NULL值 |
RIGHT JOIN 表格 ON 连接字段 | 用于按照右边表格作为主表格,完全展示右边的表格数据,左边的表格有和右边的表格相同的连接字段则展示数据,没有相同的连接字段则省略,数据为NULL值 |
FULL JOIN 表格 ON 连接字段 | 从语句结果上来说,相当于既做了LEFT JOIN 又做了 RIGHT JOIN。会全量展示左右两边表格的所有数据,如果某一边没有该条数据,则数据展示为NULL值。MySQL没有这个功能,不过魔改版如ADB等有这个功能。 |
思考题的解法
在了解了表连接的语法之后,我们再回到思考题的卡点问题上。要想将订单表和订单明细表连接起来,首先要找到订单表和订单明细表之间的连接字段。因此,得回到这两张表的表结构上:
order_item表
字段名 | 注释 |
id | 订单明细ID |
order_id | 订单ID |
goods_id | 商品ID |
goods_name | 商品名称 |
category_name_4 | 一级类目 |
category_name_3 | 二级类目 |
category_name_2 | 三级类目 |
category_name_1 | 四级类目 |
real_amount | 实际货值 |
real_count | 实际件数 |
real_weight | 实际重量 |
order表
字段名 | 注释 |
id | 订单ID |
create_time | 订单创建时间 |
customer_store_id | 店铺ID |
province_name | 收货省 |
city_name | 收货市 |
county_name | 收货区县 |
street_name | 收货街道 |
status | 订单状态 |
bd_id | BDID |
payment_amount | 实付金额 |
仔细查看这两张表的结构之后,我们会发现两张表共有订单ID这个字段,因此针对order表和order_item表我们可以使用订单ID进行连接,至于左连接还是右连接这个关系不是很大,只要你确定好用哪个作为主表,左右连接是可以做转换的。因此可以写为:
-- 右连接写法 FROM `order` t1 RIGHT JOIN order_item t2 ON t1.id = t2.order_id -- 左连接写法 FROM `order_item` t1 LEFT JOIN `order` t2 ON t1.order_id = t2.id
整个思考题的语法可以写为:
-- 左连接写法 SELECT SUM(t1.real_amount) all_amount -- 所有货值 ,SUM(IF(t2.status = 'CANCEL',t1.real_amount,NULL)) cancel_amount -- 取消单货值 ,SUM(IF(t1.goods_name LIKE '%爆品%' AND t1.goods_name NOT LIKE '%超级爆品%',t1.real_amount,NULL)) explosives_amount -- 爆品货值 ,SUM(IF(t1.goods_name LIKE '%超级爆品%',t1.real_amount,NULL)) super_explosives_amount -- 超级爆品货值 FROM order_item t1 LEFT JOIN `order` t2 ON t1.order_id = t2.id WHERE YEAR(t2.create_time) = 2022 AND MONTH(t2.create_time) = 8 -- 右连接写法 SELECT SUM(t2.real_amount) all_amount -- 所有货值 ,SUM(IF(t1.status = 'CANCEL',t2.real_amount,NULL)) cancel_amount -- 取消单货值 ,SUM(IF(t2.goods_name LIKE '%爆品%' AND t2.goods_name NOT LIKE '%超级爆品%',t2.real_amount,NULL)) explosives_amount -- 爆品货值 ,SUM(IF(t2.goods_name LIKE '%超级爆品%',t2.real_amount,NULL)) super_explosives_amount -- 超级爆品货值 FROM `order` t1 LEFT JOIN `order_item` t2 ON t2.order_id = t1.id WHERE YEAR(t1.create_time) = 2022 AND MONTH(t1.create_time) = 8
例题
获得2022年8月份,由姓毛或者姓杨的各个BD负责的店铺下单货值、实付金额、取消单货值、取消单实付金额、订单数、取消单订单数。
首先分析题:
需要知道员工的姓氏,数据来源是员工表staff,需要知道下单货值,数据来源是订单明细表order_item,需要知道订单状态、订单时间和实付金额,数据来源是订单表order
员工表和订单表之间有bd_id进行连接,订单表和订单明细表之间有订单ID进行连接。
SELECT t1.bd_id ,t3.bd_name ,SUM(t2.real_amount) real_amount ,SUM(t1.payment_amount) payment_amount ,SUM(IF(t1.status = 'CANCEL',t2.real_amount,NULL)) cancel_amount ,SUM(IF(t1.status = 'CANCEL',t1.payment_amount,NULL)) cancel_money ,COUNT(DISTINCT t1.id) order_number ,COUNT(DISTINCT IF(t1.status = 'CANCEL',t1.id,NULL)) cancel_orders FROM `order` t1 LEFT JOIN order_item t2 ON t1.id = t2.order_id LEFT JOIN staff t3 ON t1.bd_id = t3.bd_id WHERE YEAR(t1.create_time) = 2022 AND MONTH(t1.create_time) = 8 AND (t3.bd_name LIKE '毛%' OR t3.bd_name LIKE '杨%') GROUP BY t1.bd_id ,t3.bd_name