hive-sql-常用函数-留存分析-行列转换-连续登录

目录

    • hive-sql-常用函数
    • hive-sql-留存分析
    • hive-sql-连续登录
    • hive-sql-行列转换

hive-sql-常用函数

-- 返回第一个不为空的值
    select coalesce(NULL,1,2);
    -- 替换空值
    select nvl(null,0);
    -- 拼接字符
    select concat(1,2);
    select concat_ws(",",1,2)
    -- 列转行专用函数
    列转行专用函数,有时为了字段拼接效果,多和concat_ws()函数连用,见hive-sql-行列转换
    collect_list()函数有序不去重
    collect_set()无序去重
    --切割字符 返回数组
    select split("1,2,3,4,5", ",");
    -- 返回两个日期的差值 'yyyy-MM-dd HH:mm:ss' or 'yyyy-MM-dd'
    select datediff("2023-02-01","2023-02-01");
    -- 返回日期减去天数的日期
    select date_sub('2023-02-01',3);
    -- 返回日期加上天数的日期
    select date_add('2023-02-01',3);
    -- 排名函数
    row_number() 结果:12345
    rank()       结果:12245
    dense_rank() 结果:12234
    --LAG(col,n,DEFAULT) 返回窗口内往上第n行的值 新增一列
    第一个参数为列名,
    第二个参数为往上第n行(可选,默认为1),
    第三个参数为默认值(当往上第n行为NULL时候,取默认值,如不指定,则为NULL--LEAD(col,n,DEFAULT) 返回窗口内往下第n行值
    第一个参数为列名,
    第二个参数为往下第n行(可选,默认为1),
    第三个参数为默认值(当往下第n行为NULL时候,取默认值,如不指定,则为NULL-- 解析复杂数据类型
    get_json_object(字段,"$.json_key"--json_key可以使用.追加
    -- 返回日期  'yyyy-mm-dd'
    select current_date(); 
    -- 返回时间戳 "yyyy-MM-dd HH:mm:ss.ms"
    seelct current_timestamp();
    -- 返回距离1970年1月1日0点的秒数
    select unix_timestamp();
    -- 日期转时间戳函数
    select unix_timestamp('20220101','yyyymmdd');
    select unix_timestamp('20220101  16:34:13.088','yyyymmdd HH:mm:ss.ms')
    -- 时间戳转日期函数
     select from_unixtime(1641024088,'yyyyMMdd');
     select from_unixtime(1641024088,'yyyy-mm-dd HH:mm:ss.ms');
     -- 返回年月日时分秒
     select year('2022-01-01');
     select month('2022-01-01');
     select day('2022-01-01');
     select hour('2022-01-01 16:34:13.088');
     select minute('2022-01-01 16:34:13.088');
     select second('2022-01-01 16:34:13.088');
     -- 返回月份差值
     select months_between('2022-01-01','2023-01-01')
     -- 返回以当前日期开始的下一个星期几
     星期一:Monday(Mon.)
     星期二:Tuesday(Tue.)
     星期三:Wednesday(Wed.)
     星期四:Thursday(Thu.)
     星期五:Friday(Fri.)
     星期六:Saturday(Sat.)
     星期日:Sunday(Sun.select next_day("2022-02-01",'MON')
    -- 返回月份相加后的日期
    SELECT add_months('2023-01-01',4)
    -- 日期转字符串(格式化)函数:date_format
    select date_format(current_timestamp(),'yyyy-MM-dd HH:mm:ss');
    select date_format(current_date(),'yyyyMMdd');
    select date_format('2017-01-01','yyyy-MM-dd HH:mm:ss'); 
    -- yyyymmdd转yyyy-mm-dd  先转时间戳再加杠
    select from_unixtime(unix_timestamp('20220101','yyyymmdd'),'yyyy-mm-dd HH:mm:ss.ms');
    -- 字符串转时间:to_date() (字符串必须为:yyyy-MM-dd格式)
    select to_date('2017-01-01 12:12:12');
    -- 类型修改
    select cast('112' as int);
    select case when 字段 then value else colum end

hive-sql-留存分析

-- 每一天的用户的留存情况
    
    -- 有一张new_users表记录了每天的新增用户 20200501-20200601 的新增用户
    select 
    	user_id,--用户id
    	dt as new_dt --新增日期
    from new_users
    where dt >= '2020-05-01' and dt<= '2020-06-01';
    
    
    --有一张active_users表记录了每天的活跃用户数 20200501-20200601 的活跃用户
    select
    	user_id, --用户id
    	dt as active_dt, --活跃日期
    from active_users
    where dt >= '2020-05-01' and dt<= '2020-06-01';
    
    
    -- 统计当天注册 且 第N日活跃的用户 (t3): 以①为主表 left join ②
    select
    	new_users.new_dt, --用户注册时间
    	count(distinct t_new.user_id) as cnt_01, --当日注册且当日活跃的用户(当日注册肯定活跃)
    	count(distinct if(datediff(t_active.active_dt,t_new.new_dt) = 1,t_new.user_id,null)) as cnt_02,--当日注册 且 第二日活跃的用户
    	count(distinct if(datediff(t_active.active_dt,t_new.new_dt) = 2,t_new.user_id,null)) as cnt_03,--当日注册 且 第三日活跃的用户
    	count(distinct if(datediff(t_active.active_dt,t_new.new_dt) = 4,t_new.user_id,null)) as cnt_05,--当日注册 且 第五日活跃的用户
    	count(distinct if(datediff(t_active.active_dt,t_new.new_dt) = 6,t_new.user_id,null)) as cnt_07,--当日注册 且 第七日活跃的用户
    	count(distinct if(datediff(t_active.active_dt,t_new.new_dt) = 14,t_new.user_id,null)) as cnt_15,--当日注册 且 第十五日活跃的用户
    from  new_users
    left join
    t_active on t_new.user_id = t_active.user_id
    group by t_new.new_dt; // t3
    
    
    select
    	t.new_dt,--注册时间
    	t.cnt_01,--当日注册用户
    	round(cnt_02/ cnt_01 * 100, 2) as keep_02, -- 次日留存
    	round(cnt_03/ cnt_01 * 100, 2) as keep_03, -- 3日留存
    	round(cnt_05/ cnt_01 * 100, 2) as keep_05, -- 5日留存
    	round(cnt_07/ cnt_01 * 100, 2) as keep_07, -- 7日留存
    	round(cnt_15/ cnt_01 * 100, 2) as keep_15, -- 15日留存
    from t3



    -- 合并 
    select
    t.new_dt,--注册时间
    t.cnt_01,--当日注册用户
    round(cnt_02/ cnt_01 * 100, 2) as keep_02, -- 次日留存
    round(cnt_03/ cnt_01 * 100, 2) as keep_03, -- 3日留存
    round(cnt_05/ cnt_01 * 100, 2) as keep_05, -- 5日留存
    round(cnt_07/ cnt_01 * 100, 2) as keep_07, --7日留存
    round(cnt_15/ cnt_01 * 100, 2) as keep_15, -- 15日留存
    
    from
    (
    	select
    		t_new.new_dt, --用户注册时间
    		count(distinct t_new.user_id) as cnt_01, --当日注册且当日活跃的用户
    		count(distinct if(datediff(t_active.active_dt,t_new.new_dt) = 1,t_new.user_id,null)) as cnt_02,--当日注册 且 第二日活跃的用户
    		count(distinct if(datediff(t_active.active_dt,t_new.new_dt) = 2,t_new.user_id,null)) as cnt_03,--当日注册 且 第三日活跃的用户
    		count(distinct if(datediff(t_active.active_dt,t_new.new_dt) = 4,t_new.user_id,null)) as cnt_05,--当日注册 且 第五日活跃的用户
    		count(distinct if(datediff(t_active.active_dt,t_new.new_dt) = 6,t_new.user_id,null)) as cnt_07,--当日注册 且 第七日活跃的用户
    		count(distinct if(datediff(t_active.active_dt,t_new.new_dt) = 14,t_new.user_id,null)) as cnt_15,--当日注册 且 第十五日活跃的用户
    		
    	from
    	( -- 新增用户
    		select 
    			user_id,--用户id
    			dt as new_dt --新增日期
    		from new_users
    		where dt >= '2020-05-01' and dt<= '2020-06-01'
    	) t_new
    	left join
    	( --活跃用户
    		select
    			user_id, --用户id
    			dt as active_dt, --活跃日期
    		from active_users
    		where dt >= '2020-05-01' and dt<= '2020-06-01'
    	)t_active 
        on t_new.user_id = t_active.user_id
    	group by t_new.new_dt
    )t	

hive-sql-连续登录

 create external table lxdl(
 user_id string comment '用户id' ,
 login_dt string comment '登陆时间'
 )
 row format delimited fields terminated by ','
 
 1,2022-04-01
 1,2022-04-02
 1,2022-06-04
 2,2022-05-04
 2,2022-05-05
 2,2022-05-06
 3,2022-09-08
 
 
 -- row_number() + date_sub
 -- lead/lag     + datediff
 
 -- user_id string comment '用户id'
 -- login_dt sting comment '登陆时间'
 
 select
 user_id,
 min(login_dt) as start_dt, 
 max(login_dt) as end_dt,
 count(1) as continue_dt
 from
 (
 select
 user_id,
 login_dt,
 row_number()  over(partition by user_id order by login_dt) as rn  -- 每一个用户的每天登录时间
 from lxdl
 ) a group by
 user_id,date_sub(login_dt,rn)-- 分组条件是 user_id  和 date_sub(login_dt,rn) 
 -- 连续登陆,date_sub求出来是相同的
 

 -- 没有第一种直观
 
 with t1 as (select 
 user_id,
 login_dt,
 lag(login_dt,1,null) over(partition by user_id order by login_dt) as lag_dt_01,
 lead(login_dt,1,null) over(partition by user_id order by login_dt) as lead_dt_01
 from lxdl),
  t2 AS (
 select * from t1 where 
 (datediff(login_dt,lag_dt_01) = 1 and datediff(lead_dt_01,login_dt) = 1) --连续登录三天
 or datediff(login_dt,lag_dt_01) = 1 or  datediff(lead_dt_01,login_dt) = 1  -- 连续登录两天
 )
 SELECT * FROM t2

hive-sql-行列转换

-- 行转列
    《疑犯追踪》,悬疑:动作:科幻:剧情
    《Lie to me》,悬疑:警匪,动作:心理:剧情
    《战狼 2,战争:动作:灾难
    
    create external table hlzh(
    movie string comment '电影名' ,
    style string comment '类型'
    )
    row format delimited fields terminated by ','
    
    
    select
    movie,
    style_name
    from hlzh
    lateral view explode(split(style,':')) t as style_name
    
    
    -- 列转行 008| 悬疑|000| 动作|001| 科幻|002| 剧情|003| 悬疑|004| 警匪|005| 战争|006| 动作|007| 灾难|008| 科幻|
    
    create external table hlzh1(
    movie string comment '电影名',
    style string comment '类型'
    )
    row format delimited fields terminated by '|'
    
    select
    style,
    concat_ws(',',collect_list(movie)) as movies
    from hlzh1
    group by style

hive六种面试sql题型

你可能感兴趣的:(hive,sql,hadoop,大数据)