案例一分析
需要用sql实现一个逻辑,大致的逻辑内容如下:
从用户表中取出userid传入,从激活表fin_tmp.lysactivate中选取客户的最新的(create_time)额度estimate_amount,激活状态status in(4,5),该额度即为客户当前最新的额度。 激活表fin_tmp.lysactivate查无数据,返回默认值; 有数据但未激活成功记录(status in(4,5)),返回-99998; 若estimate_amount全为空,返回默认值
表1,用户表部分数据如下:
id | userid | |||
---|---|---|---|---|
1 | 11 | |||
2 | 22 | |||
3 | 33 | |||
4 | 44 | |||
5 | 55 | |||
6 | 66 | |||
7 | 77 | |||
8 | 88 | |||
9 | 99 | |||
表2,激活表部分数据如下: | ||||
id | userid | estimate_amount | status | create_time |
:----: | :----: | :----: | :----: | :---- |
1 | 11 | 25625 | 1 | 2020-03-25 |
2 | 22 | 255 | 4 | 2020-02-25 |
3 | 33 | 25225 | 5 | 2020-01-25 |
4 | 44 | 25925 | 4 | 2020-01-15 |
5 | 35 | 5 | 2020-01-14 | |
9 | 35 | 223625 | 2 | 2020-01-13 |
10 | 55 | 28925 | 3 | 2020-01-26 |
11 | 231 | 25695 | 3 | 2020-01-27 |
12 | 55 | 25620 | 5 | 2020-01-28 |
13 | 631 | 25632 | 4 | 2020-02-01 |
15 | 55 | 28925 | 4 | 2020-01-26 |
我们知道大数据测试的数据倾向于庞大型,无法一一的去核对表1的用户是否都在表2中,在sql逻辑编写的时候就需要考虑到各种各样的情况,比如从业务上来说表2中会存在多条激活信息,同时表1中的用户可能在表2中没有激活信息。 在这个逻辑中最大的难点在于,通过激活状态对整个的数据做了分离。 接下来一步步分析,对逻辑进行解读:
1、userid传入
那么这句话的内在含义就是,我得计算所有的用户数据,因为表1存在多个userid。查询时需要考虑到连接,由于我的主体是用户表的userid,那么连接时得以表1为主,即左连接时表1在左,右连接时表1在右。
2、客户的最新的(create_time)额度estimate_amount
关联到了激活表,在激活表中存在重复数据以及表1中不对应的userid激活数据,从最开始我们知道表一为主体,那么激活表中不存在于表1(用户表)的userid,已经在连接时给排除了。接下来是要处理最新和激活信息重复的问题,这个时候就需要使用到hive工具的分析函数row_number ( ) over ( PARTITION BY user_id ORDER BY c.create_time ASC )详细的使用方法看链接:链接
3、激活状态status in(4,5)
如果没有激活状态作为数据的分离条件,那么这个sql将会是很简单的,现在出现这个条件导致之前简单的加个where status in(4,5) 方法不可行了。为什么不可行?因为row_number ( )按时间对数据进行标记,这就会出现这么一种情况,每个分组的userid里面多条激活信息,但是最新的那条激活信息状态status not in(4,5),当我们where status in(4,5)时这个userid的结果为null了,与实际不符,这个时候我们需要做的是,重新修改sql的写法。将激活表分为两张表,一张表包含status in(4,5)另外一张表status not in(4,5),查询时只对status in(4,5)的这张表进行标记,以此表为主体进行左连接形成新的激活表。
案例一解决方法
由以上的具体分析,接下来就开始我们的sql解决
SELECT
re.user_id,
CASE
WHEN max( re.user_id_c ) IS NULL THEN
- 99999
WHEN max( re.status_flag ) = 0 THEN
- 99998 ELSE max( re.estimate_amount )
END AS app_num_key_qq
FROM
(
SELECT
u.user_id,
c.user_id AS user_id_c,
IF
( c.status IN ( '4', '5', '6', '7' ), 1, 0 ) AS status_flag,
t.estimate_amount
FROM
fin_tmp.loan_user u
LEFT JOIN fin_tmp.lysactivate c ON u.user_id = c.user_id
LEFT JOIN (
SELECT
u.user_id,
c.estimate_amount,
row_number ( ) over ( PARTITION BY u.user_id ORDER BY c.create_time ASC ) AS rn
FROM
fin_tmp.loan_user u
LEFT JOIN fin_tmp.lysactivate c ON u.user_id = c.user_id
AND c.status IN ( '4', '5', '6', '7' )
) t ON u.user_id = t.user_id
AND rn = 1
) re
GROUP BY
re.user_id;
案例二分析
大数据测试的时候难免会用到造一些假数据用于测试的需求,在hive里造数据,在生成中文伪数据时,存放在表中的值乱码了。这是因为Hive将按照UTF8编码格式对数据文件进行解析和查询。如果数据文件不是UTF8,则会显示乱码。其实这里面有两个方法可以解决此问题,第一种就是通过导出表中已有的数据形成文件,然后修改文件的内容,最后进行加载数据;第二种就是表中没有历史数据,需要手动插入一条数据,这个时候就需要先重新编码为utf-8然后插入到表中。
案例二解决方法
文件导入的方法
hive -e "CREATE EXTERNAL TABLE dt.test_test (
idca string,
son string ,
decilma string ,
type string
)
PARTITIONED BY (ymd string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n';"
#导出表中数据
hive -e "select * from dt.表" > /tmp/test.txt
# 在导出的txt文件中修改内容,然后再导入数据
1、load data local inpath ‘/tmp/test/test.txt’ overwrite into table dt.test_test PARTITION (ymd=“2018-12-19”);
2、load data inpath ‘yangcong/res.txt’ overwrite into table temp.test_test PARTITION (ymd=“2018-12-19”);
直接插入数据的方法 注意insert into后不要用values,而使用select,因为values不支持使用decode等函数
insert into temp.cly_user_picture select decode(binary('贷款页_'),'utf-8'),decode(binary('贷'),'utf-8'),decode(binary('理财'),'utf-8')
insert into temp.cly_user_picture select decode(binary('首页_低息贷_'),'utf-8'),decode(binary('借'),'utf-8'),decode(binary('聚财'),'utf-8')