高频HIVE-SQL笔试题详解(一)

数据库 其他数据库
最近身边有不少小伙伴在考虑跳槽的事情,免不了的会遇到一些SQL的面试题,根据过往的经历和大伙儿的反馈,我们整理归纳了一些问题出来,以供大家参考。

[[394565]]

最近身边有不少小伙伴在考虑跳槽的事情,免不了的会遇到一些SQL的面试题。

根据过往的经历和大伙儿的反馈,我们整理归纳了一些问题出来,以供大家参考。

1.连续活跃问题

这个问题有两个变形:(1)某APP用户活跃记录表active,有uid(用户id)、dt(活跃日期)字段,求出连续出勤3天及以上的用户数 (2)某APP用户活跃记录表active,有uid(用户id)、dt(活跃日期)字段,求每个用户的最大连续活跃天数 以上两个问题要求输出的数据不同,但都是要考察对于窗口函数lead、lag的掌握能力。第二个是在第一个问题基础上的延伸,也可以作为此类问题的通解。我们按照顺序分别来进行解答。首先,我们构建一个表以供测试说明,形如下图:


考虑到权限问题,这里就不单独新建hive表了,直接在with子句中union出来一个临时表:

  1. WITH active AS 
  2.   (SELECT 100 UID, 
  3.               '2021-04-01'dt 
  4.    UNION ALL SELECT 101 UID, 
  5.                         '2021-04-01'dt 
  6.    UNION ALL SELECT 102 UID, 
  7.                         '2021-04-01'dt 
  8.    UNION ALL SELECT 103 UID, 
  9.                         '2021-04-01'dt 
  10.    UNION ALL SELECT 100 UID, 
  11.                         '2021-04-02'dt 
  12.    UNION ALL SELECT 101 UID, 
  13.                         '2021-04-02'dt 
  14.    UNION ALL SELECT 102 UID, 
  15.                         '2021-04-02'dt 
  16.    UNION ALL SELECT 103 UID, 
  17.                         '2021-04-02'dt 
  18.    UNION ALL SELECT 104 UID, 
  19.                         '2021-04-02'dt 
  20.    UNION ALL SELECT 100 UID, 
  21.                         '2021-04-03'dt 
  22.    UNION ALL SELECT 104 UID, 
  23.                         '2021-04-03'dt 
  24.    UNION ALL SELECT 101 UID, 
  25.                         '2021-04-04'dt 
  26.    UNION ALL SELECT 102 UID, 
  27.                         '2021-04-04'dt 
  28.    UNION ALL SELECT 103 UID, 
  29.                         '2021-04-04'dt 
  30.    UNION ALL SELECT 104 UID, 
  31.                         '2021-04-04'dt 
  32.    UNION ALL SELECT 105 UID, 
  33.                         '2021-04-04'dt 
  34.    UNION ALL SELECT 102 UID, 
  35.                         '2021-04-03'dt) 

(1)要知道一个用户连续活跃,那么肯定是要对他的所有活跃记录进行排序的。对于active这个表,每天每个活跃用户都会有一条记录,我们将每个用户的活跃记录按日期顺序排列,如果上一条记录的日期与本条记录的日期刚好相差1天,那么这两条记录就是连续的。反过来也就是说,连续出勤的记录之间,日期差值为1,推而广之,如果用户连续出勤了N天,那么这N条记录之中任意相邻的两条都是差1天,而这段记录开始的日期到结束的日期之间的差值则是N-1。如果某用户连续出勤了4天,那么从他第3天出勤的记录往前数第6条记录就刚好是他连续出勤的开始日期,所以,我们从每条记录往前数第6条的日期与本条记录的日期差值刚好是2天的话,就表示这期间没有间断。 我们利用lead获取每一条记录其往前第2条记录的日期,与本条记录日期求差值,如果这个差值等于2,就表明该用户连续出勤了3天及以上。具体计算sql如下所示,可以求得共有3个用户连续活跃了3天及以上。

  1. select 
  2. count(DISTINCT uid) 
  3. from
  4.         SELECT UID, 
  5.                dt, 
  6.                lag(dt,2)over(PARTITION BY UID ORDER BY dt)dt2 
  7.         FROM active 
  8.         )x 
  9. where datediff(dt,dt2)=2 

这是从后往前数,同样的利用lag函数可以获取每条记录往后数第2条记录的日期,如果有差值等于2的记录,那么也可以表明用户连续出勤了3天及以上。(2)有了第一个问题作为铺垫,再来看第二个问题,相信大家应该更容易有思路了。在这个问题下,没有明确给出要计算连续多少天活跃,而是要求每个用户的最大连续活跃天数。如此一来,我们就不能直接错位相减了,而是需要清晰地找到每一段连续活跃的起止时间点。所以我们首先要判断每条记录与其相邻的记录之间是否连续,如果不连续则说明这条记录是某一段连续活跃的起点或者终点。


给所有记录标记上是否是断点之后,我们就可以为每条记录去匹配距离他最近的一次起点:

根据上图的子查询,我们就能知道每条活跃记录是从哪天开始连续活跃的了,然后求每个用户UID下所有活跃记录中与其起始日期最大的差值即可:

  1. select 
  2. UID,max(datediff(dt,start_dt))days 
  3. from
  4.     select 
  5.     UID,dt,max(if(if_continue=0,dt,null))over(PARTITION BY UID ORDER BY dt)start_dt 
  6.     from
  7.         select 
  8.         UID,dt,dt2,if(datediff(dt,dt2)=1,1,0)if_continue 
  9.         from
  10.                 SELECT UID, 
  11.                        dt, 
  12.                        lag(dt,1)over(PARTITION BY UID ORDER BY dt)dt2 
  13.                 FROM active 
  14.                 )x 
  15.     )y 
  16. )z 
  17. group by UID 

如此,就求得了所有用户的最大连续活跃天数了:

无论是第一种还是第二种,主要都是考察窗口函数的应用。熟练掌握窗口函数,并灵活运用,此类问题就不在话下了。

 

责任编辑:姜华 来源: 数师兄
相关推荐

2021-04-28 08:03:15

HIVESQLlead

2009-08-01 22:47:13

ASP.NET笔试题目ASP.NET

2021-12-08 11:18:21

Spring Bean面试题生命周期

2021-02-23 12:43:39

Redis面试题缓存

2014-04-29 14:58:24

笔试题微软笔试题

2009-06-15 17:18:25

Java笔试题

2015-04-07 14:05:13

前端阿里在线笔试题

2020-03-03 17:47:07

UDP TCP面试题

2009-06-22 13:43:00

java算法

2021-01-14 10:24:33

嵌入式笔试面试

2010-08-16 15:27:22

雅虎笔试题

2020-06-01 08:39:12

JavaScript开发技术

2010-08-18 10:17:00

2010-08-11 11:32:57

谷歌笔试题谷歌笔试题

2010-08-11 11:57:02

微软笔试题微软笔试题

2010-08-11 11:22:00

IBM笔试题IBM笔试

2010-08-11 12:07:08

腾讯笔试题腾讯笔试题

2009-07-28 13:35:18

2021-01-22 11:58:30

MySQL数据库开发

2021-04-30 08:22:36

异步求和函数
点赞
收藏

51CTO技术栈公众号