Hive left join on and where 对结果集的影响 + group by 和 row_number 的执行顺序

Hive 的 sql 过程

select * from table 历经下面几个过程:

  • 解析:将SQL字符串解析成语法树AST,判断表是否存在、字段是否正确
  • 编译:将AST编译成逻辑执行计划
  • 优化:对执行计划进行优化
  • 执行:逻辑执行计划转为物理执行计划,MR/Spark
    另外:

Hive 仅仅支持等值连接,on a.id >= b.id 不允许,on a.id = b.id 是可以的。

1,深入理解 left join on and where 筛选条件对数据的影响

下面将从实际的小例子中去一起发现 在left join 语法条件下,on and where 三个关键字对结果集产生的影响

1.1 数据准备:

order:订单表, 其中order_no有两条订单,是由于未知的业务原因造成的,属于脏数据,这里认为order_no = 2 的为脏数据。
订单表数据详情

order_goods : 订单商品表,一个订单对应多个订单商品。order_no=2 的记录的下单日期是 2021-05-23,这里由于某种原因,order_goods表中的日期错了一条。
订单商品表数据详情

1.2 on 后添加and 作为关联条件

在这里插入图片描述

1.3 on 后 添加 and(从表) 作为关联过滤条件

在这里插入图片描述

1.4 on 后面 添加 where 作为过滤条件

SQL1
SQL2

2.1 子查询

在这里插入图片描述

2.2 on 后面添加 and (针对主表)

SQL4

2.x总结:

1.不考虑where条件下,left join 会把左表所有数据查询出来,on及其后面的条件仅仅会影响右表的数据(符合就显示,不符合全部为null),如果on 后面的and 条件针对主表,满足and条件的主表记录参与和从表的匹配,不满足的直接关联的时候 填写 null值;如果on 后面and 条件针对 从表,将会对从表进行剪裁,然后再去和主表关联

2.在匹配阶段,where子句的条件都不会被使用,仅在匹配阶段完成以后,where子句条件才会被使用,它将从匹配阶段产生的数据中检索过滤,所以左连接关注的是左边的主表数据,不应该把on后面的从表中的条件加到where后,这样会影响原有主表中的数据

3.对于条件在on加个and还是用子查询,查询结果是一模一样的,至于如何使用这个需要分情况,用子查询的话会多一个maptask,但是如果利用这个子查询能过滤到很多数据的话,用子查询还是比较建议的,因为不会加载太多的数据到内存中,如果过滤数据不多的情况下,建议用on后面加and条件。

3,group by 和 row_number 的执行顺序

对于order_goods 表而言
在这里插入图片描述

SQL 1:

在这里插入图片描述

SQL 2

在这里插入图片描述

sql3

在这里插入图片描述

可以发现SQL1 等效于SQL2 ,从这里可以得出结论:
group by A,B,C 之后,A,B,C 的记录数都恒定为1,row_number等窗口函数仅仅针对group by之后的数据集,并且,where优先于 窗口函数的执行顺序

对比SQL2 和 SQL3,可以得出结论:
group by 之后进行 开窗,是对group by之后的结果进行开窗,相对于不group by (也即直接开窗)结果集更少

sql 4,
sql 5

在这里插入图片描述
而下面的语法无法通过:

select order_no
     , order_date
     , row_number() over (partition by order_no order by sku_num desc ) rk
from order_goods
group by order_no, order_date

full join 的作用

full join 在数仓中通常用来历史数据量和增量数据的合并,从下面的例子中注意where 条件的前后顺序对 full join 之后的结果集的影响:

-- full join 主表t1 会在full join 之后 where 是不一样的,这一点和left join 并不相同
select coalesce(t1.field, t2.field) as field
from `table_A` t1
full join
(
    select *
    from `table_A`
    where date_id = '${D-T_1}'
) t2
on t1.id = t2.id
where t1.date_id = '${D-T}'
;

select coalesce(t1.field, t2.field) as field
from (
    select *
    from `table_A`
    where date_id = '${D-T}'
) t1
full join
(
    select *
    from `table_A`
    where date_id = '${D-T_1}'
) t2
on t1.id = t2.id
;

left semi join (左半连接) 的作用

从下面的case中取理解 left semi join 的作用:

select t1.id, t1.fieldA
from `table_A` t1
where t1.id in (
    select id
    from `tmp_B`
)
;
-- 改写为:
select t1.* -- 不允许出现t2 的字段
from `table_A` t1
left semi join  `table_B` t2
on (t1.id = t2.id)
;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值