hive实现用户连续登陆的最大天数

hive实现用户连续登陆的最大天数,第1张

假设说我们现在有这样一张表

连续登陆,也就是在连续登陆的期间内,后一天和前一天的差值为1,不能为大于1的值,直到间断。那么在这里其实我们可以设置一列序号,如果是连续的话,这列序号也是会随着日期同步增长的,那么日期减去这个序号,应该都是一个确定的日期。比如说9月16号对应的序号是1,9月17号对应的序号是2,9月18号对应的序号是3,那么9月16号-1=9月15号,同理,9月17号-2=9月15号,都是同样的日期。那么我们根据这个日期和user_id和日期标示进行分组即可。

我们可以看到用ROW_NUMBER()函数已经成功加上了一列。

我们用log_date这一列减去row_number这一列得到一个时间标志

在这里做的事情是把之前的rn从string的格式改为了int的格式,这样才能够传入到date_sub函数里面做减法。这里要注意,做subquery的时候要制定子表格的名字,比如我在这里就指定了子表格名字为c。

接下来我们要根据user_id和log_date进行分组然后统计。

现在我们已经得到了每个日期的分组的数目统计,这里的天数实际上是开始连续的那个日期-1(因为不连续的都不是同一个标志日,不会分到一组)但是还有两个问题,一个是要求出每个id的最大值,另外就是要将天数加1回到一开始连续开始的日期。

以上解决了找到最大值,但是最大值的日期没有返回。

由于嵌套写得太多了,接下来还是新建一张表格,用连接的方式找出最大日期

如果原始数据表有连续的日期,应该考虑用dense_number(),同样的 *** 作后,用select distinct的方法来选出user_id, date以及symbol_date都不一样的一行。

关于这个问题可以参考链接:

hivesql sql — 获取指定hive表或指定文件所hive表DDL按区则默认执行近7区DDL同table支持符合sql语则表达式表匹配则提示用户选择(使用file则自关闭该交互功能)

在过去几年中,主要受到围绕Stinger计划的Hive社区创新的推动,Hive查询时间得到了显着改善,使Hive能够以速度和规模支持批量和交互式工作负载。

但是,许多使用者仍然不熟悉以最快速度运行Hive查询的基本技术和最佳实践。本文中,将重点介绍一些常使用的简单技术,以提高HIVE查询的性能。

Hive可以使用Apache Tez执行引擎而不是Map-reduce引擎。不会详细介绍这里提到的使用Tez的许多好处; 相反,提出一个简单的建议:如果在您的环境中默认情况下没有打开它,请在Hive查询的开头使用Tez设置为“true”

Hive支持ORCfile,这是一种新的表存储格式,通过谓词下推,压缩等技术实现极佳的速度提升。

对每个HIVE表使用ORCFile应该是一个明智的选择,对于获得HIVE查询的快速响应时间非常有益。

作为一个例子,考虑两个大表A和B(存储为文本文件,这里没有指定一些列),以及一个简单的查询 :

此查询可能需要很长时间才能执行,因为表A和B都存储为TEXT。将这些表转换为ORCFile格式通常会显着缩短查询时间:

ORC支持压缩存储(使用ZLIB或如上所示使用SNAPPY),但也支持未压缩存储。

将基表转换为ORC通常是取决于所在团队获取数据的职责,由于其他优先级,可能需要一些时间来更改完整的获取数据过程。ORCFile的好处是如此明显,以至于推荐如上所示的自助式方法 - 将A转换为A_ORC,将B转换为B_ORC并以此方式进行连接,以便立即从更快的查询中受益,而不依赖于其他团队。

矢量化查询执行通过一次批量执行1024行而不是每行一行来提高扫描,聚合,过滤器和连接等 *** 作的性能。

这个功能在Hive 013中引入,显着缩短了查询执行时间,并且可以通过两个参数设置轻松启用:

在提交最终执行之前,Hive会优化每个查询的逻辑和物理执行计划。这些优化不是基于查询的成本 - 也就是说,直到运行时。

最近添加到Hive,基于成本的优化,基于查询成本执行进一步优化,从而导致可能不同的决策:如何订购联接,执行哪种类型的联接,并行度等。

要使用基于成本的优化(也称为CBO),请在查询开头设置以下参数

然后,通过运行Hive的“analyze”命令为CBO准备数据,以收集我们想要使用CBO的表的各种统计信息。

例如,在tweet数据表中,希望收集有关该表的统计信息以及大约2列:“sender”和“topic”:

使用HIVE 014(在HDP 22上),analyze命令的工作速度要快得多,而且您不需要指定每一列,因此只需如下:

现在使用此表执行查询应该会导致不同的执行计划由于成本计算和Hive创建的不同执行计划而更快。

SQL是一种强大的声明性语言。与其他声明性语言一样,编写SQL语句的方法不止一种。尽管每个语句的功能都相同,但它可能具有截然不同的性能特征

每条记录代表一次点击事件,希望找到每个sessionID的最新网址。

有人使用如下方式:

在上面的查询中,构建一个子查询来收集每个会话中最新事件的时间戳,然后使用内部联接来过滤掉其余的事件。

虽然查询是一个合理的解决方案 - 从功能的角度来看 - 事实证明,有一种更好的方法来重写这个查询,如下所示

在这里,使用Hive的OLAP功能(OVER和RANK)来实现相同的功能,但没有使用表连接。

显然,删除不必要的连接几乎总能带来更好的性能,而且当使用大数据时,这比以往任何时候都更重要。在很多情况下查询不是最优的 - 所以仔细查看每个查询并考虑重写是否可以使它更好更快。

更多内容信息 >

笔记:

1窗口函数边界:

复购率: 当前月份购买2次及以上的客户占所有客户比例

回购率:当前月份购买且上个月份也购买的客户占当月所有月份客户比例

思路:

复购率

1、对当月(2月份)的客户分组,计数购买次数

2、筛选购买次数为2以上的,认为是复购群体

回购率

1、筛选当月及上月部分

2、利用客户id进行当月连上月,推荐左连

3、对同一条客户id均有购买记录的,认为是回购群体

注意:

1连接条件中,条件1为客户key字段,表示同一个客户;条件2为两个月的信息连接(本月日期 = 上月日期 +1个月)

2ADD_MONTHS:别忘了有个's',add_months只能对完整日期格式进行月份加减(add_months(‘yyyy-MM-dd hh:mm:ss’,N),add_months(‘yyyy-MM-dd’,N)),所以这里先用concat给'年月'增加一个'日'字段,其中N为正则增加,N为负则减少

第一步:根据用户分组,求出用户购买的产品及顺序

cpzl_zw1是cpzl_zw的上一个购买的产品

第三步:为相邻的产品添加排序(即上面lag函数添加的产品)

若相邻产品的排序为3,则表示第三件产品,题目要求前两件产品,则可以根据小于3进行筛选

步骤:

第一步:将两表进行连接(customer为主表)

第二步:按城市、产品进行聚合分组,求出销量

第三步:窗口函数对销量进行排序

第四步:where进行筛选(where不能直接对窗口函数结果进行筛选,所以要再次使用表子连接)

提示:只用到订单表 ods_sales_orders,并列排序 dense_rank 窗口函数

日期变换:

(1)dt转日期

to_date(from_unixtime(unix_timestamp('${dt}','yyyyMMdd')))

(2)日期转dt

regexp_replace('${date}','-','')

(3)dt转当月1号日期

to_date(from_unixtime(unix_timestamp(concat(substr('${dt}',1,6),'01'),'yyyyMMdd')))

trunc(to_date(from_unixtime(unix_timestamp('${dt}','yyyyMMdd'))),'MM')

-- 下月1号日期

trunc(add_months(to_date(from_unixtime(unix_timestamp('${dt}','yyyyMMdd'))),1),'MM')

(4)dt转当周星期一日期

next_day(date_add(to_date(from_unixtime(unix_timestamp('${dt}','yyyyMMdd'))), -7), 'Mo')

date_sub(next_day(to_date(from_unixtime(unix_timestamp('${dt}','yyyyMMdd'))),'MO'),7)

-- 下周星期一日期

next_day(to_date(from_unixtime(unix_timestamp('${dt}','yyyyMMdd'))),'MO')

(5)dt前六天日期(dt为星期天时得到的是本周周一的日期)

date_add(to_date(from_unixtime(unix_timestamp('${dt}','yyyyMMdd'))), -6)

(5)dt转当季第一天日期

if(length(floor(substr('${dt}',5,2)/31)3+1)=1,concat(substr('${dt}',1,4),'-0',floor(substr('${dt}',5,2)/31)3+1,'-01'),concat(substr('${dt}',1,4),'-',floor(substr('${dt}',5,2)/31)3+1,'-01'))

(6)dt转半年第一天日期

if(length(floor(substr('${dt}',5,2)/61)6+1)=1,concat(substr('${dt}',1,4),'-0',floor(substr('${dt}',5,2)/61)6+1,'-01'),concat(substr('${dt}',1,4),'-',floor(substr('${dt}',5,2)/61)6+1,'-01'))

(7)dt转当年1号日期

concat(substr('${dt}',1,4),'-01-01')(8)在同时有日周月粒度时要注意数据的时间范围,有时每月的第一个自然周会跨月,比如2019年3月的第一周的日期是20190225-20190303where agent_business_date between date_add_day('${dt}',-31) and to_date(from_unixtime(unix_timestamp('${dt}','yyyyMMdd')))where dt between regexp_replace(date_add_day('${dt}',-31),'-','') and '${dt}'

------------------------------------------------------------------------------------------

-- 日期维度表表结构edw_publicdim_esf_edw_pub_date

------------------------------------------------------------------------------------------

col_name data_type comment

------------------------------------------------------------------------

calendar_date string 日期,格式为"YYYY-MM-DD"

week_english_name string 星期英文名

week_chinese_name string 星期中文名

day_of_week_number int 所属一周当中的第几天

calendar_month_code string 日期所属月份,格式为"YYYY-MM"

calendar_month_number int 所属月份数字

month_english_name string 月份英文名

month_chinese_name string 月份中文名

day_of_month_number int 所属月份当中的第几天

calendar_quater_code string 日期所属季度,格式为"YYYY-QT"

calendar_quater_number int 所属季度数字

day_of_quater_number int 所属季度当中的第几天

calendar_half_year_code string 日期所属半年,格式为"YYYY-HY"

calendar_half_year_number int 所属半年数字,1为上半年,2为下半年

calendar_year_code string 日期所属年份,格式为"YYYY"

day_of_year_number int 所属年份当中的第几天

work_day_flag string 工作日标志: Y - 是/ N - 否

holiday_flag string 节假日标志: Y - 是/ N - 否

-- 日期维度表的使用

-- 当天日期

SELECT

calendar_date

FROM

edw_publicdim_esf_edw_pub_date

WHERE

calendar_date = regexp_replace('${dt}','(\\d{4})(\\d{2})(\\d{2})','$1-$2-$3')

-- Finereport中日周月季半年年 各周期末日期的算法

select

${if(粒度 == 1," case when date(max(calendar_date))>=date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) else date(max(calendar_date)) end as period_end_date","")}

${if(粒度 == 2," distinct case when day_of_week_number = 1 and date_add('day',6,date(calendar_date)) >=date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) when day_of_week_number = 7 and date(calendar_date) >=date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) when day_of_week_number = 1 then date_add('day',6,date(calendar_date)) when day_of_week_number = 7 then date(calendar_date) else date(calendar_date) end as period_end_date ","")}

${if(粒度 == 3," case when date(max(calendar_date))>=date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) else date(max(calendar_date)) end as period_end_date ","")}

${if(粒度 == 4," case when date(max(calendar_date))>=date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) else date(max(calendar_date)) end as period_end_date ","")}

${if(粒度 == 5," case when date(max(calendar_date))>=date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) else date(max(calendar_date)) end as period_end_date ","")}

${if(粒度 == 6," case when date(max(calendar_date))>=date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) else date(max(calendar_date)) end as period_end_date ","")}

from

edw_publicdim_esf_edw_pub_date

where calendar_date >= '${开始时间}' and calendar_date <= '${结束时间}'

${if(粒度 == 1," group by calendar_date ","")}

${if(粒度 == 2," and day_of_week_number in (1,7) ","")}

${if(粒度 == 3," group by calendar_month_code ","")}

${if(粒度 == 4," group by calendar_quater_code ","")}

${if(粒度 == 5," group by calendar_year_code ","")}

${if(粒度 == 6," group by calendar_half_year_code ","")}

-- Finereport中日周月季半年年 各周期期初期末日期的算法(这种计算方法当前日期是20190330,输入的日期范围是2019-03-01至2091-03-28则输出的月日期范围是2019-03-29)

select

${if(粒度 == 1,"date(calendar_date) as period_start_date, date(calendar_date) as period_end_date ","")}

${if(粒度 == 2,"case when day_of_week_number = 1 then date(calendar_date) when day_of_week_number = 7 then date_add('day',-6, date(calendar_date)) end as period_start_date, case when day_of_week_number = 1 and date_add('day',6, date(calendar_date)) >=date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) when day_of_week_number = 7 and date(calendar_date)>=date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) when day_of_week_number = 1 then date_add('day',6, date(calendar_date)) when day_of_week_number = 7 then date(calendar_date) end as period_end_date ","")}

${if(粒度 == 3,"date(calendar_date) as period_start_date, case when date_add('day',-day(date(calendar_date)),date_add('month',1,(date(calendar_date))))>=date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) else date_add('day',-day(date(calendar_date)),date_add('month',1,(date(calendar_date)))) end as period_end_date ","")}

${if(粒度 == 4,"calendar_date as period_start_date,date_add('day',-1,date_add('month',1,date(substr(calendar_date,1,4)||'-'||cast(cast(floor(cast(substr(calendar_date,6,2) as int)/31)3+3 as int) as varchar)||'-01'))) as period_end_date ","")}

${if(粒度 == 5,"date(concat(substr(calendar_date,1,4),'-01','-01')) as period_start_date,case when date(concat(substr(calendar_date,1,4),'-12','-31'))>= date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) else date(concat(substr(calendar_date,1,4),'-12','-31')) end as period_end_date","")}

${if(粒度 == 6,"date(min(calendar_date)) as period_start_date,case when date(max(calendar_date))>= date(date_add('day',-1,current_date)) then date(date_add('day',-1,current_date)) else date(max(calendar_date)) end as period_end_date","")}

from

edw_publicdim_esf_edw_pub_date

where calendar_date >= '${开始时间}' and calendar_date <= '${结束时间}'

${if(粒度 == 1," and 1 = 1 ","")}

${if(粒度 == 2," and day_of_week_number in (1,7) ","")}

${if(粒度 == 3," and day_of_month_number = 1","")}

${if(粒度 == 4," and day_of_quater_number = 1","")}

${if(粒度 == 5," and day_of_year_number = 1","")}

${if(粒度 == 6," group by calendar_half_year_code ","")}

------------------------------------------------------------------------------------------------

-- 根据输入的时间范围计算期末日期

------------------------------------------------------------------------------------------------

select t1

from

-- 日周月季年半年不同粒度的统计数据各存为了一张表

edw_reportsadm_xf_edw_house_sub_project_report_00${dtype}ly_di t1--日报

join

(

-- 日

SELECT

calendar_date

FROM

edw_publicdim_esf_edw_pub_date

WHERE

calendar_date BETWEEN '${bdt}' AND '${edt}'

AND '${dtype}' = '1_dai'

UNION

-- 月

SELECT

MAX(calendar_date) AS calendar_date

FROM

edw_publicdim_esf_edw_pub_date

WHERE

calendar_date BETWEEN '${bdt}' AND '${edt}'

AND '${dtype}' = '2_dai'

GROUP BY

calendar_month_number

UNION

-- 周

SELECT

calendar_date

FROM

edw_publicdim_esf_edw_pub_date

WHERE

calendar_date BETWEEN '${bdt}' AND '${edt}'

AND day_of_week_number = 7

AND '${dtype}' = '3_dai'

UNION

-- 季

SELECT

MAX(calendar_date) AS calendar_date

FROM

edw_publicdim_esf_edw_pub_date

WHERE

calendar_date BETWEEN '${bdt}' AND '${edt}'

AND '${dtype}' = '4_dai'

GROUP BY

calendar_quater_code

UNION

-- 年

SELECT

MAX(calendar_date) AS calendar_date

FROM

edw_publicdim_esf_edw_pub_date

WHERE

calendar_date BETWEEN '${bdt}' AND '${edt}'

AND '${dtype}' = '5_dai'

GROUP BY

calendar_year_code

UNION

-- 半年

SELECT

MAX(calendar_date) AS calendar_date

FROM

edw_publicdim_esf_edw_pub_date

WHERE

calendar_date BETWEEN '${bdt}' AND '${edt}'

AND '${dtype}' = '6_dai'

GROUP BY

calendar_half_year_code

UNION

SELECT

MAX(calendar_date) AS calendar_date

FROM

edw_publicdim_esf_edw_pub_date

WHERE

calendar_date BETWEEN '${bdt}' AND '${edt}'

ORDER BY

calendar_date

) t2

on t1statistic_date = t2calendar_date

where

statistic_date between '${bdt}' and '${edt}'

${if(len(tenant_name) == 0,"","and house_sub_project_organization_short_name = '" + tenant_name + "'")}

${if(len(status) == 0,"","and house_sub_project_cooperation_status_code = " + status)}

${if(len(tenant_type) == 0,"","and house_sub_project_organization_business_type_code= " + tenant_type)}

${if(len(project_type) == 0,"","and house_sub_project_cooperation_type_code= " + project_type)}

order by statistic_date

       在hive中,我们经常需要进行日期的计算,可是,经常会出现这样一种情况,hive仓库中日期的存储格式是yyyyMMdd,例如20200520,在进行日期的计算时,hive支持的函数例如,add_months 仅识别yyyy-MM-dd格式的函数,如果输入yyyyMMdd的参数,返回结果是null。所以我们在对日期的字段进行计算时,优先需要进行格式的转换,将yyyyMMdd转换成yyyy-MM-dd格式

转换方式如下:亲测可用

DATE(from_unixtime(unix_timestamp('20171205','yyyymmdd'),'yyyy-mm-dd'))

以上就是关于hive实现用户连续登陆的最大天数全部的内容,包括:hive实现用户连续登陆的最大天数、用HIVESQL怎么获取上一个月的月份、5种让Hive查询变快的方法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9339897.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存