经典Hive SQL面试题

本文提供了10道经典的Hive SQL面试题,涵盖各种需求场景,包括数据准备和实际查询SQL的实现,帮助你提升Hive查询技能,为面试做好充分准备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一题

需求

我们有如下的用户访问数据
	userId  visitDate   visitCount
	u01 2017/1/21   5
	u02 2017/1/23   6
	u03 2017/1/22   8
	u04 2017/1/20   3
	u01 2017/1/23   6
	u01 2017/2/21   8
	U02 2017/1/23   6
	U01 2017/2/22   4
要求使用SQL统计出每个用户的累积访问次数,如下表所示:
	用户id    月份  小计  累积
	u01 2017-01 11  11
	u01 2017-02 12  23
	u02 2017-01 12  12
	u03 2017-01 8   8
	u04 2017-01 3   3

实现

数据准备
CREATE TABLE test_sql.test1 ( 
		userId string, 
		visitDate string,
		visitCount INT )
	ROW format delimited FIELDS TERMINATED BY "\t";
	INSERT INTO TABLE test_sql.test1
	VALUES
		( 'u01', '2017/1/21', 5 ),
		( 'u02', '2017/1/23', 6 ),
		( 'u03', '2017/1/22', 8 ),
		( 'u04', '2017/1/20', 3 ),
		( 'u01', '2017/1/23', 6 ),
		( 'u01', '2017/2/21', 8 ),
		( 'u02', '2017/1/23', 6 ),
		( 'u01', '2017/2/22', 4 );
查询SQL
SELECT t2.userid,
	   t2.visitmonth,
	   subtotal_visit_cnt,
	   sum(subtotal_visit_cnt) over (partition BY userid
									 ORDER BY visitmonth) AS total_visit_cnt
FROM
  (SELECT userid,
		  visitmonth,
		  sum(visitcount) AS subtotal_visit_cnt
   FROM
	 (SELECT userid,
			 date_format(regexp_replace(visitdate,'/','-'),'yyyy-MM') AS visitmonth,
			 visitcount
	  FROM test_sql.test1) t1
   GROUP BY userid,
			visitmonth)t2
ORDER BY t2.userid,
		 t2.visitmonth

第二题

需求

有50W个京东店铺,每个顾客访客访问任何一个店铺的任何一个商品时都会产生一条访问日志,
访问日志存储的表名为Visit,访客的用户id为user_id,被访问的店铺名称为shop,数据如下:

				u1	a
				u2	b
				u1	b
				u1	a
				u3	c
				u4	b
				u1	a
				u2	c
				u5	b
				u4	b
				u6	c
				u2	c
				u1	b
				u2	a
				u2	a
				u3	a
				u5	a
				u5	a
				u5	a
请统计:
(1)每个店铺的UV(访客数)
(2)每个店铺访问次数top3的访客信息。输出店铺名称、访客id、访问次数

实现

数据准备
CREATE TABLE test_sql.test2 ( 
						 user_id string, 
						 shop string )
			ROW format delimited FIELDS TERMINATED BY '\t';	
			INSERT INTO TABLE test_sql.test2 VALUES
			( 'u1', 'a' ),
			( 'u2', 'b' ),
			( 'u1', 'b' ),
			( 'u1', 'a' ),
			( 'u3', 'c' ),
			( 'u4', 'b' ),
			( 'u1', 'a' ),
			( 'u2', 'c' ),
			( 'u5', 'b' ),
			( 'u4', 'b' ),
			( 'u6', 'c' ),
			( 'u2', 'c' ),
			( 'u1', 'b' ),
			( 'u2', 'a' ),
			( 'u2', 'a' ),
			( 'u3', 'a' ),
			( 'u5', 'a' ),
			( 'u5', 'a' ),
			( 'u5', 'a' );			

查询SQL实现
(1)方式1:
		SELECT shop,
			   count(DISTINCT user_id)
		FROM test_sql.test2
		GROUP BY shop
方式2:
		SELECT t.shop,
			   count(*)
		FROM
		  (SELECT user_id,
				  shop
		   FROM test_sql.test2
		   GROUP BY user_id,
					shop) t
		GROUP BY t.shop
(2)	
SELECT t2.shop,
	   t2.user_id,
	   t2.cnt
FROM
  (SELECT t1.*,
		  row_number() over(partition BY t1.shop
							ORDER BY t1.cnt DESC) rank
   FROM
	 (SELECT user_id,
			 shop,
			 count(*) AS cnt
	  FROM test_sql.test2
	  GROUP BY user_id,
			   shop) t1)t2
WHERE rank <= 3					

第三题

需求

已知一个表STG.ORDER,有如下字段:Date,Order_id,User_id,amount。
数据样例:2017-01-01,10029028,1000003251,33.57。
请给出sql进行统计:
(1)给出 2017年每个月的订单数、用户数、总成交金额。
(2)给出2017年11月的新客数(指在11月才有第一笔订单)

实现

数据准备
CREATE TABLE test_sql.test3 ( 
			dt string,
			order_id string, 
			user_id string, 
			amount DECIMAL ( 10, 2 ) )
ROW format delimited FIELDS TERMINATED BY '\t';
INSERT INTO TABLE test_sql.test3 VALUES ('2017-01-01','10029028','1000003251',33.57);
INSERT INTO TABLE test_sql.test3 VALUES ('2017-01-01','10029029','1000003251',33.57);
INSERT INTO TABLE test_sql.test3 VALUES ('2017-01-01','100290288','1000003252',33.57);
INSERT INTO TABLE test_sql.test3 VALUES ('2017-02-02','10029088','1000003251',33.57);
INSERT INTO TABLE test_sql.test3 VALUES ('2017-02-02','100290281','1000003251',33.57);
INSERT INTO TABLE test_sql.test3 VALUES ('2017-02-02','100290282','1000003253',33.57);
INSERT INTO TABLE test_sql.test3 VALUES ('2017-11-02','10290282','100003253',234);
INSERT INTO TABLE test_sql.test3 VALUES ('2018-11-02','10290284','100003243',234);
查询SQL
(1)
SELECT t1.mon,
	   count(t1.order_id) AS order_cnt,
	   count(DISTINCT t1.user_id) AS user_cnt,
	 
<think>嗯,用户想找Hive SQL相关的面试题和答案。首先,我需要回忆一下常见的Hive面试问题,比如窗口函数、数据转换、去重等等。根据提供的引用内容,看到有同时在线人数、行转列、列转行等问题。比如引用[1]中的同时在线人数计算,用到了UNION ALL和窗口函数sum() over(),这个应该是经典问题之一。还有引用[3]中的collect_list函数用来拼接字符串,这也是常见的行转列问题。引用[4]提到的split和explode则是列转行的例子。 接下来需要整理这些问题,并给出对应的答案和示例代码。用户可能需要分点回答,结构清晰。比如第一个问题同时在线人数,需要步骤分解,说明如何将登录登出时间合并,然后用窗口函数累加。第二个问题行转列,用collect_list或者concat_ws。第三个问题列转行,用lateral view explode。第四个数据去重,可以用row_number或者group by。第五个连续登录,用日期差和分组统计。 还要注意用户的系统级指令,比如数学公式用$...$,代码块正确使用格式,引用标记在末尾。比如在回答每个问题时,适当引用提供的参考资料,如[^1]、[^3]、[^4]等。同时生成相关问题,可能包括性能优化、其他函数应用、处理数据倾斜等。 需要确保每个问题都有对应的SQL示例,并且代码正确。比如在同时在线人数的问题中,UNION ALL合并登录登出记录,然后sum(tag) over计算实时人数。在行转列中,collect_list和concat_ws的使用。列转行中的split和explode组合。 还要注意用户提到的“生成相关问题”部分,需要列出几个相关的问题,比如优化方法、其他窗口函数应用、数据倾斜处理等,这样用户可以有进一步的学习方向。 最后,检查是否所有引用都正确标注,答案是否符合中文要求,结构是否清晰,有没有遗漏常见的Hive面试题。可能需要补充一些其他常见问题,比如分区和分桶的区别、Hive和传统数据库的区别等,但根据提供的引用内容,主要围绕已有例子展开。</think>### Hive SQL 常见面试问题及答案 #### 1. **如何计算某时段内同时在线的最多人数?** **答案**: 将登录时间标记为$+1$,登出时间标记为$-1$,合并后通过窗口函数累加计算实时人数。示例代码: ```sql WITH t1 AS ( SELECT login_ts ts, 1 AS tag FROM user_login_detail UNION ALL SELECT logout_ts ts, -1 AS tag FROM user_login_detail ) SELECT MAX(cn) AS max_online_count FROM ( SELECT SUM(tag) OVER (ORDER BY ts) AS cn FROM t1 ) t2; ``` **解析**: - 使用`UNION ALL`合并登录和登出动作的时间戳。 - 窗口函数`SUM(tag) OVER (ORDER BY ts)`按时间顺序累加人数,最终取最大值。 --- #### 2. **如何将多行数据合并为一行(行转列)?** **答案**: 使用`COLLECT_LIST()``COLLECT_SET()`聚合函数,结合`CONCAT_WS()`拼接字符串。示例: ```sql SELECT user_id, CONCAT_WS(',', COLLECT_LIST(product_id)) AS purchased_products FROM purchase_table GROUP BY user_id; ``` **解析**: - `COLLECT_LIST`收集所有商品ID(允许重复),`COLLECT_SET`去重。 - `CONCAT_WS`用逗号分隔拼接结果。 --- #### 3. **如何将一行数据拆分为多行(列转行)?** **答案**: 使用`LATERAL VIEW``EXPLODE()`函数展开数组。示例: ```sql SELECT name, subject_name FROM student_table LATERAL VIEW EXPLODE(SPLIT(subject_list, ',')) extend_sub AS subject_name; ``` **解析**: - `SPLIT(subject_list, ',')`将字符串转换为数组。 - `EXPLODE()`展开数组,`LATERAL VIEW`生成多行结果。 --- #### 4. **如何对重复数据进行去重?** **答案**: 使用`ROW_NUMBER()`窗口函数标记重复项,或直接使用`GROUP BY`。示例: ```sql -- 方法1:窗口函数 SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_ts DESC) AS rn FROM login_table ) t WHERE rn = 1; -- 方法2:GROUP BY SELECT user_id, MAX(login_ts) AS last_login FROM login_table GROUP BY user_id; ``` --- #### 5. **如何统计用户连续登录天数?** **答案**: 通过日期差与分组标记实现。示例: ```sql WITH t1 AS ( SELECT user_id, login_date, DATE_SUB(login_date, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date)) AS grp FROM login_table ) SELECT user_id, COUNT(*) AS consecutive_days FROM t1 GROUP BY user_id, grp HAVING COUNT(*) >= 3; -- 连续3天以上 ``` **解析**: - `DATE_SUB(login_date, ROW_NUMBER())`生成连续登录的分组标记[^2]。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值