当前位置:   article > 正文

多表关联——内连接和外连接_内关联

内关联

多表关联

场景:面对不同表里面的不同字段(从不同表里取不同字段合并起来)

补充知识:理解多表关联原理——笛卡尔积

  • 利用多表关联我们可以从不同的表取需要的字段
  • 在实际中,我们需要分析好业务逻辑,明确取数的规则或者逻辑后再进行查询
  • 要考虑不同字段分析可以从哪些表取—有的字段可以从多张表取,有的字段只能从某张表取

内关联

  • 内关联是针对列进行操作的
  • 表与表之间需要通过相同意思的字段关联才有意义

join on 语句

select A.字段1,B.字段2,C.字段3

from 表A

(inner)join 表B  on  表A.字段=表B.字段

(inner)join 表C  on  表A.字段=表B.字段

……

where.条件

group by 汇总

  • 可以把select   from   jion on 看作一张表
  • where.条件 可以针对上述所有表

用以下列图片来对 jion on 语句进行说明

把订单明细表和订单表通过 order_id 和 id 关联起来 

Select t1.order_id , t2.id

From order_item t1

Join order t2 on t1.order_id = t2.id;

注意事项:

  1. 在多表关联的时候:select 后面的列一定是表名.字段(避免关联的相关表有名字相同的字段)
  2. 在多表关联中,必须给每个表取别名,这样就更方便
  3. 多表关联时,必须用相同意义的字段,但并不代表字段的名称是一样的
  4. 表中的字段名一样,并不意味着两个字段表示的意思也是一样的

使用案例及常见问题 

简单运用:从订单表中查和与订单明细表共有的id记录

  • 先对比,从订单表中查询所有id

  • 利用多表关联查询订单表中和订单明细表中相同的id

  • 同时查询两表中共有的id

  1. -- 1、先对比,从订单表中查询所有id
  2. select id
  3. from db_order.sn_order_20210412;
  4. -- 2、利用多表关联查询订单表中和订单明细表中相同的id
  5. select t1.id
  6. from sn_order_20210412 t1
  7. join sn_orderitem_20210412 t2 on t2.order_id = t1.id;
  8. -- 3、同时查询两表中共有的id
  9. select t1.id,t2.order_id
  10. from sn_order_20210412 t1
  11. join sn_orderitem_20210412 t2 on t2.order_id = t1.id;

 实际案例:统计会员购买的金额,购买的订单数,购买的商品数

  • 先分别查看两表

  • 分析:

  1. 购买金额:order表

  2. 购买订单数:order表/orderitem表

  3. 购买商品数:orderitem表

  1. -- 先分别查看两表
  2. select *
  3. from db_order.sn_order_20210412
  4. limit 2;
  5. select *
  6. from db_order.sn_orderitem_20210412
  7. limit 2;
  8. -- 关联两表
  9. select t1.member_id
  10. ,sum(t1.order_money) as money
  11. ,count(t1.id) as order_num1
  12. ,count(t2.order_id) as order_num2
  13. ,count(distinct t1.id) as order_num3
  14. ,sum(t2.item_num) as item_num
  15. from db_order.sn_order_20210412 t1
  16. join db_order.sn_orderitem_20210412 t2 on t1.id =t2.order_id
  17. group by t1.member_id ;
查询结果
 member_idmoneyorder_num1order_num2order_num3item_num
 1600.90000926618
52400.3000492217
121982213
1350.800000192222
计数4 12   

  注意,以上查询出现逻辑错误:

  1. 关联的时候,订单表的会员数比原来订单表的会员数是不是少了?为什么? ——4 vs 14
  2. 关联以后,订单数量多了 订单应该是24张 ——24 vs 12
  3. 累计购买金额也不对——参看补充知识:笛卡尔积

简单分析问题

查询关联前的会员数及订单数量

  1. -- 关联前会员查询
  2. select distinct member_id
  3. from db_order.sn_order_20210412;
  4. select count(distinct member_id) as member_num
  5. from db_order.sn_order_20210412;
查询结果
member_id23451131158921131129999
会员数14
  1. -- 关联前订单及订单数量
  2. select distinct id
  3. from db_order.sn_order_20210412;
  4. select count(distinct id)
  5. from db_order.sn_order_20210412;
查询结果
idA002A003A004A005A006A007A008A009A010A011A012A014A015A016A017A018A019A020A001A2222A00000A11111A22222A5555
订单数量24

 总结:内关联会导致匹配不上的数据丢失

外连接

场景:保留匹配不上的数据不丢失

左关联:左表的所有信息都包括进去

select 表1.字段A,表2.字段B

from 表名1

left(inner) join 表名2 on 关联字段

where……

右关联:右表的所有信息都包括进去

select *

from 表名1

right(inner) join 表名2 on 关联字段

where……

尝试用左关联解决实战案例:统计会员购买的金额,购买的订单数,购买的商品数

  • 方案一 :出现问题——累计金额数据丢失
  1. -- 用 left join 把所有的会员信息保留
  2. select member_id
  3. ,sum(t1.price*t1.item_num) as order_money /*order_money数据是从订单明细表里取的,所以有的会员消费金额会丢失*/
  4. ,count(distinct t.id) as order_number
  5. ,sum(t1.item_num) as item_number /*注意数据的意义,item_num已经表示商品数量,所以需要用求和函数sum而非计数函数count*/
  6. from sn_order_20210412 t
  7. left join db_order.sn_orderitem_20210412 t1 on t.id = t1.order_id
  8. group by member_id
  9. order by sum(t1.item_num) desc;
查询结果
member_idorder_moneyorder_numberitem_number
1200.368
51,200.1517
129913
1350.8000001932
2[NULL]1[NULL]
3[NULL]1[NULL]
4[NULL]1[NULL]
8[NULL]1[NULL]
9[NULL]1[NULL]
11[NULL]1[NULL]
15[NULL]2[NULL]
21[NULL]1[NULL]
31[NULL]1[NULL]
9,999[NULL]5[NULL]
代码逻辑错误:order_money 数据丢失
  • 方案二:出现问题——累计订单金额数据重复
  1. -- 1、先构造一个子查询
  2. select member_id
  3. ,t.id
  4. ,order_money
  5. ,t1.item_num
  6. from db_order.sn_order_20210412 t
  7. left join db_order.sn_orderitem_20210412 t1 on t1.order_id =t.id ;
  8. -- 2、嵌套子查询
  9. select member_id
  10. ,sum(order_money) as order_money
  11. ,count(distinct t2.id) as order_number /*从临时表里提取数据,t2.id*/
  12. ,sum(item_num) as item_number /*不带表名?*/
  13. from (select member_id
  14. ,t.id
  15. ,order_money
  16. ,t1.item_num
  17. from db_order.sn_order_20210412 t
  18. left join db_order.sn_orderitem_20210412 t1 on t1.order_id =t.id ) t2
  19. group by member_id
  20. order by sum(item_num) desc;
查询结果
member_idorder_moneyorder_numberitem_number
11,088.6568
52,400.3017
1219813
1353.1000001432
21001[NULL]
312.100000381[NULL]
4200.14999391[NULL]
8100.15000151[NULL]
920.149999621[NULL]
110.1500000061[NULL]
15130.89999962[NULL]
21110.15000151[NULL]
311,215.101[NULL]
9,9994205[NULL]
逻辑错误:order_money 数据重复
  • 方案三:解决了数据重复和数据丢失问题

  1. select member_id
  2. ,sum(order_money) as order_money
  3. ,count(distinct t.id) as order_number
  4. ,sum(item_num) as item_number
  5. from db_order.sn_order_20210412 t
  6. left join (select order_id
  7. ,sum(item_num) as item_num
  8. from db_order.sn_orderitem_20210412
  9. group by order_id) t1
  10. on t1.order_id = t.id
  11. group by member_id
  12. order by sum(item_num) desc;
查询结果
member_idorder_moneyorder_numberitem_number
1688.050010768
51,200.1517
129913
1353.1000001432
21001[NULL]
312.100000381[NULL]
4200.14999391[NULL]
8100.15000151[NULL]
920.149999621[NULL]
110.1500000061[NULL]
15130.89999962[NULL]
21110.15000151[NULL]
311,215.101[NULL]
9,9994205[NULL]

 逻辑错误原因分析及解决问题

补充知识——左关联构建的笛卡尔积表

1、先构建两个演示表

左表
订单号订单金额会员号创建时间订单状态
A0051200.1552017/1/1 13:232
A01999122017/2/11 13:231

 

 

 

 

右表
订单商品ID订单号商品ID商品名称商品价格商品数量
AB004A0051001A0.151
AB005A0051004D2006

 

 

 

 

2、构建笛卡尔积表

笛卡尔积表
订单号订单金额会员号创建时间订单状态订单商品ID订单号商品ID商品名称商品价格商品数量
A0051200.1552017/1/1 13:232AB004A0051001A0.151
A0051200.1552017/1/1 13:232AB005A0051004D2006
A01999122017/2/11 13:231AB004A0051001A0.151
A01999122017/2/11 13:231AB005A0051004D2006

 

 

 

 

 

 

笛卡尔积表做左关联后
订单号订单金额会员号创建时间订单状态订单商品ID订单号商品ID商品名称商品价格商品数量
A0051200.1552017/1/1 13:232AB004A0051001A0.151
A0051200.1552017/1/1 13:232AB005A0051004D2006
A01999122017/2/11 13:231nullnullnullnullnullnull
出现问题:订单金额没有办法计算

 

 

 

 

 

 

3、修改bug——保持左表不动,构建一个临时表作为右表

左表
订单号订单金额会员号创建时间订单状态
A0051200.1552017/1/1 13:232
A01999122017/2/11 13:231

 

 

 

 

右表
订单号商品数量
A0057

 

 

 

4、把临时表和左表进行左关联

左关联
订单号订单金额会员号创建时间订单状态订单号商品数量
A0051200.1552017/1/1 13:232A0057
A01999122017/2/11 13:231nullnull
解决了数据重复和丢失的问题

 

 

 

 

 

注意事项:

  • 针对内关联出现的数据缺失问题可以用外关联来解决
  • 一般使用左关联,左关联是会保留我们左边表的所有信息;把数据比较全的表放在左边,避免数据丢失
  • 很多时候统计的时候,外关联经常会结合子查询来使用,但是构建临时表时要先分析问题,避免出现逻辑错误
  • 上述实战案例出现问题
  1. 关联后直接sum(order_money),会导致数据有重复
  2. 关联后sum(t1.price*t1.item_num),会导致数据丢失

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/626322
推荐阅读
相关标签
  

闽ICP备14008679号