Hive SQL 面试题 - 统计每日新增用户

SQL查询每日新增用户数,
通过user_login_detail表,使用SQL的开窗函数row_number对用户按登录时间排序,找出每个用户的首次登录日期,然后进行聚合计算,每天的新增用户数为首次登录的用户数。最后通过HAVING子句筛选出非零用户数的日期。

1 需求

从用户登录明细表(user_login_detail)中查询每天的新增用户数,若一个用户在某天登录了,且在这一天之前没登录过,则认为该用户为这一天的新增用户。

  • 用户登录明细表:user_login_detail
user_id(用户id)ip_address(ip地址)login_ts(登录时间)logout_ts(登出时间)
101180.149.130.1612021-09-21 08:00:002021-09-27 08:30:00
102120.245.11.22021-09-22 09:00:002021-09-27 09:30:00
10327.184.97.32021-09-23 10:00:002021-09-27 10:30:00
  • 期望结果
login_date_first (日期)user_count (新增用户数)
2021-09-211
2021-09-221
2021-09-231
2021-09-241
2021-09-251
2021-09-261
2021-09-271
2021-10-042
2021-10-061

2 解答

  • 思路

观察用户登录明细表,需要使用到的信息有 用户 id用户登录时间 这两个字段,这里认为用户都被限制为单点登录,所以登出时间字段用不到。

考虑使用开窗函数中的排名函数对每一个用户按照登录时间进行排名,再对排名进行限定,仅取第一次登录的日期作为新用户首次登录,最后根据日期分组,查看每天存在多少个用户即可。

  • 实现

1 开窗,此处使用 row_number 进行编号,over 中指定 partition by user_id 表示针对每一个用户进行编号,指定 order by login_ts 表示按照 login_ts 排序之后再编号

SELECT 
	user_id,
  	substr(login_ts, 1, 10) dt,
	row_number() over (partition by user_id order by login_ts) rn
from user_login_detail
user_iddtrn
1012021-09-211
1012021-09-272
1012021-09-283
1012021-09-294
1012021-09-305
10102021-10-091
10102021-09-272

2 聚合,在第一步的结果上,按照 dt 字段进行聚合,结合 sum(if()) 进行统计,最后使用 HAVING 进行聚合结果的筛选

select dt login_date_first, sum(if(rn == 1, 1, 0)) user_count from (
	SELECT 
    	user_id,
  		substr(login_ts, 1, 10) dt,
		row_number() over (partition by user_id ORDER by login_ts) rn
	from user_login_detail
) t1 group by dt HAVING sum(if(rn == 1, 1, 0)) != 0 order by dt;
login_date_firstuser_count
2021-09-211
2021-09-221
2021-09-231
2021-09-241
2021-09-251
2021-09-261
2021-09-271
2021-10-042
2021-10-061
### 大数据场景下的手写SQL面试题及答案解析 #### 常见的手写SQL面试题 在大数据领域,SQL作为数据分析的核心工具之一,其重要性不言而喻。以下是几个常见且具有代表性的手写SQL面试题及其解答。 --- #### 1. **统计每天新增用户的数量** 假设有一张用户表 `users`,结构如下: - `id`: 用户ID - `name`: 用户- `created_at`: 创建时间 (日期格式) **问题**: 编写一条 SQL 查询语句,按天统计每天新增用户数量。 ```sql SELECT DATE(created_at) AS date, COUNT(*) AS new_users_count FROM users GROUP BY DATE(created_at) ORDER BY date; ``` 这条查询通过 `DATE()` 函数提取创建时间中的日期部分,并按照该字段分组计数[^4]。 --- #### 2. **计算两个时间段内的活跃用户重叠量** 假设有两张日志表 `log_table_a` 和 `log_table_b`,分别记录了不同应用的日活用户情况。每张表都有以下字段: - `user_id`: 用户唯一标识符 - `date`: 登录日期 **问题**: 计算某一天(如 '2023-09-01')在这两份日志中都登录过的用户总数。 ```sql SELECT COUNT(DISTINCT a.user_id) AS overlap_user_count FROM log_table_a a JOIN log_table_b b ON a.user_id = b.user_id WHERE a.date = '2023-09-01' AND b.date = '2023-09-01'; ``` 此查询利用 JOIN 将两张表关联起来,筛选出符合条件的用户并去重。 --- #### 3. **找出最近一次购买商品的时间** 假设有一个订单表 `orders`,包含以下字段: - `order_id`: 订单编号 - `customer_id`: 客户ID - `product_name`: 商品名称 - `purchase_date`: 购买时间 **问题**: 对于每一个客户,找到他们最后一次购买的商品以及对应的购买时间。 ```sql WITH latest_purchase AS ( SELECT customer_id, MAX(purchase_date) AS last_purchase_time FROM orders GROUP BY customer_id ) SELECT o.customer_id, o.product_name, o.purchase_date FROM orders o JOIN latest_purchase lp ON o.customer_id = lp.customer_id AND o.purchase_date = lp.last_purchase_time; ``` 这段代码先通过子查询获取每位客户的最大购买时间,再将其与原表连接得到具体商品信息。 --- #### 4. **实现 Map 端 Join 的逻辑模拟** MapReduce 中经常涉及分布式环境下的 join 操作。如果需要手动编写 SQL 来模拟 map 端 join,则可以考虑以下方式: 假设存在一张缓存文件 `/wordcount/cache/user.txt`,其中存储了一些预定义的数据集合。我们需要将这些数据加载并与另一张表进行匹配操作。 **问题**: 如何用 SQL 表达这种基于外部资源的映射关系? 虽然标准 SQL 不支持直接读取 HDFS 文件路径,但在某些框架扩展中可以通过 UDF 或者虚拟表来完成类似功能。例如,在 Hive 中可借助 `add file` 加载本地脚本或配置参数。 --- #### 总结 以上列举了几类典型的大数据环境下可能遇到的手写 SQL 面试题,涵盖了基础聚合运算、多表联接分析以及复杂窗口函数的应用等内容。值得注意的是,实际工作中还需要结合业务需求灵活调整方案设计思路[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值