row_num引起的数据差异

news/2024/11/17 19:08:56/

一、背景

在对一个Hive历史Job优化后需要比对两张结果表的数据,发现有一张表两个字段有一些差异(优化只是加了优化参数没有修改逻辑,所以数据有差异是不正常的)

二、定位

根据差异字段定位到是一张临时表里面的使用了row_num引起的

1、现象

就是以下代码在同一天不同时间段跑,最终数据量不一致

drop table if exists  tz0002_v2 purge; 
create external table tmp_tz0002_v2 stored as orc tblproperties ('external.table.purge'='true')  as
select cast(vip_card as bigint) member17_nbr,date_format(a.operate_time,'yyyy-MM')   as auto_renew_month    --签约年月
from (select card_no as vip_card,case when status='1' then '签约' when status='-1' then '解约' else status end status, operate_time, -- 操作时间row_number() over (partition by card_no order by operate_time desc) rnfrom auto_renew_sign_d t1 where date_format(t1.operate_time,'yyyy-MM-dd') <= '${yestoday_str}'  )awhere rn=1and status='签约'
group by  cast(vip_card as bigint), date_format(a.operate_time,'yyyy-MM')
;
select count(1) as cnt , 'v1' as type from tz0002_v1
union all 
select count(1) as cnt , 'v2' as type from tz0002_v2
+----------+-------+
|   cnt    | type  |
+----------+-------+
| 2748473  | v1|
| 2748463  | v2|
+----------+-------+

2、找出差异的id

select a.*
from 
tz0002_v1  a
left join tz0002_v2  b
on a.member17_nbr=b.member17_nbr
where b.member17_nbr is null;

拿具体差异的id查看数据

select
uid
,card_no
,status
,operate_time
,row_number() over (partition by card_no order by operate_time desc) rn
from  cn_ods_dmp_secure.o_bas_auto_renew_sign_d
where card_no='107421002798006351';
;
+--------------+--------------------+---------+----------------------+-----+
|     uid      |      card_no       | status  |     operate_time     | rn  |
+--------------+--------------------+---------+----------------------+-----+
| 18181734302  | 107421002798006351  | 1       | 2023-05-14 13:56:19  | 1   |
| 18181734302  | 107421002798006351  | -1      | 2023-05-14 13:56:19  | 2   |
| 18181734302  | 107421002798006351  | 1       | 2022-11-29 16:10:29  | 3   |
| 18181734302  | 107421002798006351  | -1      | 2022-04-09 12:06:28  | 4   |
| 18181734302  | 107421002798006351  | 1       | 2021-12-07 13:37:42  | 5   |
+--------------+--------------------+---------+----------------------+-----+

以card_no分组operate_time倒序排序,会发现最新的两条记录 operate_time相同,status不同【那么不同时间跑有可能这次排序号1的是状态等于1的,下次跑是状态等于-1的】,最终会取状态等于1的且rn等于1的数据

最后然后发现每个ID会有一个update_time,而且最新时间两条不同状态的数据update_time不相同,那么在row_num中将operate_time 修改成update_time更加符合具体业务逻辑,得到的数据也更加准确

+--------------------+---------+----------------------+----------------------+
|      card_no       | status  |     operate_time     |     update_time      |
+--------------------+---------+----------------------+----------------------+
| 107421002798006351  | 1       | 2021-12-07 13:37:42  | 2021-12-07 13:37:44  |
| 107421002798006351  | -1      | 2022-04-09 12:06:28  | 2022-04-09 12:06:29  |
| 107421002798006351  | 1       | 2022-11-29 16:10:29  | 2022-11-29 16:10:32  |
| 107421002798006351  | 1       | 2023-05-14 13:56:19  | 2023-05-14 13:56:19  |
| 107421002798006351  | -1      | 2023-05-14 13:56:19  | 2023-05-14 13:56:20  |
+--------------------+---------+----------------------+----------------------+

三 、修复

将代码修改成下面

drop table if exists  tz0002_v2 purge; 
create external table tmp_tz0002_v2 stored as orc tblproperties ('external.table.purge'='true')  as
select cast(vip_card as bigint) member17_nbr,date_format(a.operate_time,'yyyy-MM')   as auto_renew_month    --签约年月
from (select card_no as vip_card,case when status='1' then '签约' when status='-1' then '解约' else status end status, operate_time, -- 操作时间row_number() over (partition by card_no order by update_time desc) rnfrom auto_renew_sign_d t1 where date_format(t1.operate_time,'yyyy-MM-dd') <= '${yestoday_str}'  )awhere rn=1and status='签约'
group by  cast(vip_card as bigint), date_format(a.operate_time,'yyyy-MM')
;

经过测试不同时间段跑出来的结果都是相同的,以前同事上线的历史代码修改后再比对数据也是正常的


http://www.ppmy.cn/news/606089.html

相关文章

arcgis栅格影像裁剪--shp

1、打开软件&#xff0c;导入数据&#xff0c;如下&#xff1a; 2、裁剪面形状如下&#xff0c;为shp文件&#xff1a; 3、在arctoolbox中找到"数据管理工具"--"栅格"--"栅格处理"--"裁剪"工具&#xff0c;如下&#xff1a; 4、打开裁…

LeetCode简单题之三角形的最大周长

题目 给定由一些正数&#xff08;代表长度&#xff09;组成的数组 nums &#xff0c;返回 由其中三个长度组成的、面积不为零的三角形的最大周长 。如果不能形成任何面积不为零的三角形&#xff0c;返回 0。 示例 1&#xff1a; 输入&#xff1a;nums [2,1,2] 输出&#xff1…

构建同元素的列表

5*[pad] 构建同元素的列表

云边端与边缘计算技术

云边端与边缘计算技术 边缘计算&#xff0c;是指在靠近物或数据源头的一侧&#xff0c;采用网络、计算、存储、应用核心能力为一体的开放平台&#xff0c;就近提供最近端服务。其应用程序在边缘侧发起&#xff0c;产生更快的网络服务响应&#xff0c;满足行业在实时业务、应用智…

LeetCode简单题之托普利茨矩阵

题目 给你一个 m x n 的矩阵 matrix 。如果这个矩阵是托普利茨矩阵&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 如果矩阵上每一条由左上到右下的对角线上的元素都相同&#xff0c;那么这个矩阵是 托普利茨矩阵 。 示例 1&#xff1a; 输入&#xff…

unicode-utf8转换

代码 #ifndef UNICONVERT_H #define UNICONVERT_H#include <string>using std::string;namespace unicodeCvt{typedef unsigned int uint;//0x80 -> 10xx xxxx BF//0xC0 -> 110x xxxx 1F//0xE0 -> 1110 xxxx 0F//0xF0 -> 1111 0xxx 07void func(uint…

list extend 和 append

append 一次追加一个列表 extend 一次追加所有的元素 单个的形式加入

LeetCode简单题之按奇偶排序数组 II

题目 给定一个非负整数数组 nums&#xff0c; nums 中一半整数是 奇数 &#xff0c;一半整数是 偶数 。 对数组进行排序&#xff0c;以便当 nums[i] 为奇数时&#xff0c;i 也是 奇数 &#xff1b;当 nums[i] 为偶数时&#xff0c; i 也是 偶数 。 你可以返回 任何满足上述条件…