【AI生成+补充】高频 hql的面试问题 以及 具体sql

以下是高频HQL面试题及对应SQL示例,涵盖核心语法、优化技巧和典型场景,可直接用于面试准备:

一、基础操作与DDL

1. 创建分区表 & 动态插入分区

sql

复制代码
-- 创建外部分区表(按日期分区)
CREATE EXTERNAL TABLE logs (
    user_id STRING,
    event STRING,
    duration INT
) PARTITIONED BY (dt STRING)  -- 分区字段
STORED AS ORC
LOCATION '/user/hive/warehouse/logs';

-- 动态插入分区(自动创建分区目录)
SET hive.exec.dynamic.partition=true;
SET hive.exec.dynamic.partition.mode=nonstrict;

INSERT INTO TABLE logs PARTITION (dt)
SELECT user_id, event, duration, event_date AS dt  -- 最后一列为分区字段
FROM raw_logs;

二、查询优化

2. 分桶表创建 & SMB Join优化

sql

复制代码
-- 创建分桶排序表(分桶数4,按user_id排序)
CREATE TABLE users_bucketed (
    user_id STRING,
    name STRING
) CLUSTERED BY (user_id) SORTED BY (user_id) INTO 4 BUCKETS
STORED AS ORC;

-- 启用SMB Join
SET hive.optimize.bucketmapjoin=true;
SET hive.auto.convert.sortmerge.join=true;

SELECT /*+ MAPJOIN(b) */ 
    a.user_id, a.event, b.name
FROM logs a JOIN users_bucketed b 
ON a.user_id = b.user_id;  -- 避免Shuffle

三、窗口函数实战

3. 计算连续3天活跃用户

sql

复制代码
SELECT user_id
FROM (
    SELECT 
        user_id,
        dt,
        LAG(dt, 2) OVER (PARTITION BY user_id ORDER BY dt) AS lag2  -- 取前2天的日期
    FROM logs
    WHERE event = 'active'
) t
WHERE datediff(dt, lag2) = 2;  -- 当前日期与前2天日期差2天(连续3天)
// add by me-方法二

SQL统计连续登陆3天的用户(连续活跃超3天用户)_sql连续登录3天用户数-CSDN博客

SELECT user_id,

count(1) AS cnt

FROM

(SELECT user_id, DATE_SUB(dt, rn) AS sub_date

FROM

(SELECT user_id, dt, row_number() over( partition by user_id ORDER BY dt) AS rn

FROM logs) t

GROUP BY user_id, sub_date

) diffTable

GROUP BY user_id, sub_date

HAVING cnt >= 3

连续登陆(含间隔)

ll​​​​​​​https://zhuanlan.zhihu.com/p/29641524870

4. 分组Top N(部门工资前三)

sql

复制代码
SELECT dept, name, salary
FROM (
    SELECT 
        dept, name, salary,
        DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS rk
    FROM employees
) t
WHERE rk <= 3;
5,去除最大最小值求均值

https://zhuanlan.zhihu.com/p/28466428027

6.波峰波谷(快手)

https://zhuanlan.zhihu.com/p/1885646993512200080

7,AI无效oncall

https://zhuanlan.zhihu.com/p/1893678485387588081


四、数据倾斜解决方案

5. 大表Join倾斜Key打散

sql

复制代码
-- 假设user_id='999'是倾斜Key
SELECT *
FROM (
    SELECT 
        user_id,
        event,
        CASE WHEN user_id = '999' THEN concat(user_id, '_', rand())  -- 打散倾斜Key
             ELSE user_id END AS join_key
    FROM logs
) a
JOIN users b
ON a.join_key = b.user_id;

五、高级函数与转换

6. 行列转换

sql

复制代码
-- 行转列(聚合多行)
SELECT 
    user_id,
    CONCAT_WS(',', COLLECT_LIST(event)) AS events  -- 合并事件列表
FROM logs
GROUP BY user_id;

-- 列转行(拆分数组)
SELECT user_id, event_name
FROM logs
LATERAL VIEW EXPLODE(SPLIT(events, ',')) e AS event_name;  -- events是逗号分隔字符串
7. JSON解析

sql

复制代码
SELECT 
    get_json_object(json_col, '$.user.id') AS user_id,
    json_tuple(json_col, 'event', 'timestamp') AS (event, ts)  -- 同时解析多字段
FROM json_logs;

六、性能优化技巧

8. 谓词下推优化

sql

复制代码
-- 优化前(全表扫描)
SELECT * FROM logs WHERE dt = '2023-08-12' AND duration > 1000;

-- 优化后(分区裁剪+列裁剪)
SELECT user_id, event  -- 只取所需列
FROM logs
WHERE dt = '2023-08-12'   -- 分区字段过滤
  AND duration > 1000;    -- ORC格式下自动谓词下推
9. MapJoin手动指定

sql

复制代码
SELECT /*+ MAPJOIN(small_table) */ 
    big_table.id, small_table.name
FROM big_table 
JOIN small_table ON big_table.id = small_table.id;

七、场景题模板

10. 留存率计算(次日留存)

https://www.zhihu.com/question/294871305/answer/1903544000008417365

sql

复制代码
SELECT 
    a.dt,
    COUNT(DISTINCT a.user_id) AS dau,
    COUNT(DISTINCT b.user_id) AS next_day_retained,
    COUNT(DISTINCT b.user_id) / COUNT(DISTINCT a.user_id) AS retention_rate
FROM (
    SELECT dt, user_id FROM logs WHERE event='login' 
) a
LEFT JOIN (
    SELECT dt, user_id FROM logs WHERE event='login'
) b 
ON a.user_id = b.user_id
AND b.dt = DATE_ADD(a.dt, 1)  -- 次日留存
GROUP BY a.dt;

高频考点总结

类型 关键点
语法 PARTITIONED BY vs CLUSTERED BYLATERAL VIEW explode()
窗口函数 ROW_NUMBER()/RANK()/DENSE_RANK()LAG()/LEAD()ROWS BETWEEN
优化 分区裁剪、列裁剪、MapJoin、SMB Join、随机数打散倾斜Key
复杂类型处理 COLLECT_LIST()/COLLECT_SET()get_json_object()
实战场景 留存率、连续登录、Top N、UV/PV统计

提示:面试时务必说明优化原理(如 "SMB Join通过分桶排序避免Shuffle"),并强调数据倾斜处理经验。

几个关键函数

ROWS BETWEEN

sum(sales_volume) over(rows between 1 preceding and current row) sum_sales

sum(sales_volume) over(rows between current row and unbounded following)

sum(sales_volume) over(rows between unbounded preceding and current row) sum_sales

sum(sales_volume) over(rows between current row and 2 following) sum_sales

sum(sales_volume) over(rows between 1 preceding and current row) sum_sales

LAG()/LEAD()

LAG(column_name, offset, default_value) OVER (PARTITION BY partition_column ORDER BY sort_column)

LEAD(column_name, offset, default_value) OVER (PARTITION BY partition_column ORDER BY sort_column)

示例场景

假设有员工薪资表 emp,包含 ename(姓名)、job(职位)、sal(薪资)。

  • 获取前一行薪资 ‌:LAG(sal, 1) OVER (ORDER BY sal) 可获取当前行前一行薪资。 ‌1
  • 设置默认值 ‌:LAG(sal, 1, 3.1415) 当前行无前一行数据时,默认返回3.1415。 ‌1
  • 连续性检查 ‌:通过 LAG(sal, 1)LEAD(sal, 1) 组合,可验证薪资是否连续。 ‌24

ROW_NUMBER()/RANK()/DENSE_RANK()

dense_rank() over(partition by class order by pjs.sn_scores desc) as dense_rank

rank() over(partition by class order by pjs.sn_scores desc) as rank

row_number() over(partition by class order by pjs.sn_scores desc) as row_number

假设学生成绩表按分数降序排列:

  • ‌**ROW_NUMBER()**‌:1, 2, 3, 4, 5(完全按顺序分配) ‌12
  • ‌**RANK()**‌:1, 2, 2, 4(相同分数共享排名,后续跳过) ‌15
  • ‌**DENSE_RANK()**‌:1, 2, 2, 3(相同分数仍保持连续排名) ‌25

[ PARTITIONED BY ] vs [ CLUSTERED BY ]

CLUSTERED BY(分桶表设置)

作用:在建表时指定数据的分桶规则,物理上把数据分到多个文件(桶)中。

示例:

CREATE TABLE table_name (col1 INT, col2 STRING)

CLUSTERED BY (col1) INTO 4 BUCKETS;

原理:Hive 会根据col1的哈希值将数据分散到 4 个桶中,查询时可加速数据读取。

SORTED BY(桶内排序设置)

作用:在建表时指定桶内数据的排序规则。

示例:

CREATE TABLE table_name (col1 INT, col2 STRING)

CLUSTERED BY (col1) SORTED BY (col2 ASC) INTO 4 BUCKETS;

应用:适合需要频繁按col2过滤的场景,如时间字段。

DISTRIBUTED BY(MapJoin 优化)

作用:在INSERT OVERWRITE语句中控制数据分发,常用于优化 MapJoin。

示例:

INSERT OVERWRITE TABLE target_table

SELECT * FROM source_table

DISTRIBUTED BY (join_key);

PARTITIONED BY(分区表定义)

作用:创建分区表,数据按分区字段物理存储在不同目录中。

示例:

CREATE TABLE table_name (col1 INT, col2 STRING)

PARTITIONED BY (dt STRING);

查询优化:

SELECT * FROM table_name WHERE dt = '2023-01-01'; -- 直接过滤分区目录

上表来源:

HiveSQL 入门避坑指南:搞懂这些 "BY",让你的 SQL 少跑 80% 的冤枉路_hive cluster by作用-CSDN博客

LATERAL VIEW explode()

Hive之explode()函数和posexplode()函数和lateral view函数_lateral view explode函数-CSDN博客

Hive中的explode函数、posexplode函数与later view函数_hive explode-CSDN博客

相关推荐
李剑一13 分钟前
面试官:watch和computed的区别?不要简单的说监听器和计算属性!
前端·面试
专研狂20 分钟前
小问题需要注意
面试
Java中文社群1 小时前
说说内存泄漏的常见场景和排查方案?
java·后端·面试
C4程序员2 小时前
北京JAVA基础面试30天打卡08
java·开发语言·面试
Hilaku2 小时前
从“高级”到“资深”,我卡了两年和我的思考
前端·javascript·面试
快去睡觉~2 小时前
力扣11:盛水最多的容器
算法·leetcode·职场和发展
秋天的一阵风3 小时前
😈 藏在对象里的 “无限套娃”?教你一眼识破循环引用诡计!
前端·javascript·面试
似水流年流不尽思念3 小时前
如何实现一个线程安全的单例模式?
后端·面试
码出极致4 小时前
Java 四大引用类型:从概念到场景的核心区别全解析
后端·面试