欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

由于LEFT JOIN错误使用导致的数据不一致问题

程序员文章站 2024-01-30 15:34:46
...

msyql语句执行顺序
代码的执行顺序:
from... where...group by... having.... select ... order by...
hive 语句执行顺序
大致顺序
from... where.... select...group by... having ... order by...

LEFT JOIN有一个作用就是用于去除表A中表B的数据,现在我们来用几个示例来分析SQL执行顺序问题,以Hive为例:

错误示例一

SELECT * FROM(
SELECT rr.datekey,
               A.goods_id,
               B.poi_id B_poi_id               
          FROM A
          LEFT JOIN B
            ON A.poi_id = B.poi_id 
            WHERE A.datekey=20170403 AND B.datekey = 20170403) rs
         WHERE rs.B_poi_id IS NULL;

分析:此时先 ON LEFT JOIN 关联A B表,此时再用WHERE 选取了A.datekey=20170403并且B.datekey = 20170403的行,所以不会存在rs.B_poi_id IS NULL 的行了。

错误示例二:

SELECT rr.datekey,
               A.goods_id,
               B.poi_id B_poi_id               
          FROM A
          LEFT JOIN B
            ON A.poi_id = B.poi_id 
            WHERE A.datekey=20170403 AND B.datekey = 20170403 AND B.poi_id IS NULL

分析:这个也是属于逻辑混乱的,同上,在 ON LEFT JOIN后WHERE选取了A.datekey=20170403 AND B.datekey = 20170403 AND B.poi_id IS NULL 同时成立的行,这种就是不可能存在的,同一行不会B.datekey = 20170403 AND B.poi_id IS NULL成立。

错误示例三:

SELECT rr.datekey,
               A.goods_id,
               B.poi_id B_poi_id               
          FROM A
          LEFT JOIN B
            ON A.poi_id = B.poi_id AND A.datekey=20170403 AND B.datekey = 20170403 
            WHERE B.poi_id IS NULL

分析:这种presto和hive都跑不出来数据,最后job fail。

正确示例一:

SELECT rr.datekey,
               A.goods_id,
               B.poi_id B_poi_id               
          FROM A
          LEFT JOIN B2
          (SELECT B.poi_id 
          FROM B
          WHERE B.datekey = 20170403)AS B2
            ON A.poi_id = B2.poi_id
            WHERE A.datekey=20170403 AND B2.poi_id IS NULL

分析:通过子查询先查出B中这一天的数据,A再和B2 LEFT JOIN,最后选取A.datekey 和 B2.poi_id IS NULL 的行,正确。

正确示例二:

SELECT rr.datekey,
               A.goods_id,
               B.poi_id B_poi_id               
          FROM A
          LEFT JOIN B
            ON A.poi_id = B.poi_id  AND B.datekey = 20170403
            WHERE A.datekey=20170403 AND B.poi_id IS NULL

分析:这个其实就是上面的简化版,因为在ON里面先过滤了就是和上面的子查询是一样的道理。