hive函数的解析及练习

将 SQL 函数从"语法"转化为"解决商业问题的能力",关键在于建立起"业务场景-函数逻辑"的映射思维。这就像手里有了一把瑞士军刀,现在我们要学习在什么情况下用哪一把刀。

为了让你能系统性地掌握,我们将 Hive 中最核心的函数分为三个梯队:计算与逻辑类时间处理类高阶分析类。每一类我都将结合具体的商业场景进行拆解。


🛠️ HQL 高级开发与复杂逻辑实现(实战拆解)

窗口函数

窗口函数是 Hive SQL 的灵魂,用于解决"组内排序"、"累计计算"等问题。

  • 排名类
    • row_number() over(partition by dept order by salary desc):用于TopN问题(如:每个部门工资最高的前 3 名)。
    • rank() vs dense_rank():处理并列排名的区别(1, 1, 3 vs 1, 1, 2)。
  • 偏移类
    • lag(visit_date, 1) over(partition by uid order by visit_date):获取用户上一次登录时间。
    • 实战:计算"用户上次登录时间"与"本次登录时间"的差值,如果差值 > 30天,则标记为"流失召回用户"。
    • lead():获取下一次登录时间,用于计算留存。
  • 聚合类
    • sum(sales) over(partition by month order by day rows between unbounded preceding and current row):用于计算累计求和(如:本月截止到今天的总销售额)。
复杂数据类型处理
  • 场景 :APP 启动日志通常是一行 JSON,里面包含一个 events 数组(用户在本次启动中触发了点击、浏览等多个事件)。
  • 处理
    • 使用 get_json_object 解析基础字段。
    • 使用 explode(split(events, ',')) 将数组炸开,一行变多行,才能统计每个具体事件的点击量。
    • lateral view:配合 explode 使用,防止数据膨胀导致的主表数据丢失问题。
行列转换
  • 行转列
    • 场景:将"科目-分数"表转换为"姓名-语文-数学-英语"表。
    • 技术max(case when subject='math' then score else 0 end) 配合 group by name
  • 列转行
    • 场景:将"姓名-语文-数学"表转换为"科目-分数"长表。
    • 技术stack(2, 'math', math_score, 'chinese', chinese_score) 或者 array + explode
常用函数
  • collect_set(col):将分组内的某列数据去重合并成一个数组。
    • 实战 :找出"购买了商品 A 同时也购买了商品 B"的用户。先按用户分组,collect_set(item_id),然后判断数组中是否同时包含 A 和 B。
  • concat_ws(',', collect_set(tag)):将用户的多个标签合并成一个逗号分隔的字符串,形成用户画像标签串。

第一梯队:基础逻辑与计算(解决"指标定义"问题)

商业分析的第一步往往是数据清洗和指标分类。

1. 条件逻辑函数

核心函数CASE WHEN, COALESCE, IF, NVL
应用场景:用户分层、异常值处理、指标口径定义。

商业案例:定义高价值用户

假设你需要统计不同等级用户的订单量。业务定义:金额 > 1000 为"高价值",> 500 为"中价值",其余为"普通"。

复制代码
SELECT
    order_id,
    user_id,
    amount,
    CASE
        WHEN amount >= 1000 THEN '高价值'
        WHEN amount >= 500 THEN '中价值'
        ELSE '普通'
    END AS user_level
FROM dwd_order_detail;

进阶用法(行转列统计)

如果要统计各等级用户的总数,可以配合 SUM 使用(这是面试和实战的高频考点):

复制代码
SELECT
    SUM(CASE WHEN amount >= 1000 THEN 1 ELSE 0 END) AS high_val_cnt,
    SUM(CASE WHEN amount >= 500 AND amount < 1000 THEN 1 ELSE 0 END) AS mid_val_cnt
FROM dwd_order_detail;
2. 空值处理

核心函数COALESCE(value1, value2, ...)
商业案例 :营销活动中的替补策略。

如果用户有"优惠券金额",则用优惠券;如果没有,看是否有"积分抵扣";如果都没有,显示 0。

复制代码
SELECT
    user_id,
    COALESCE(coupon_amt, point_deduction, 0) AS final_discount
FROM marketing_info;

第二梯队:时间与日期函数(解决"周期分析"问题)

电商、金融、物流等所有行业都离不开时间维度分析。

1. 日期解析与计算

核心函数date_format, datediff, date_add, last_day
应用场景:复购率计算、留存分析、账期统计。

商业案例:计算用户复购间隔

计算用户两次下单之间相隔了多少天。这需要用到 LAG (后面会讲) 配合 datediff

商业案例:判断是否月底冲刺

统计每个月的最后一天的订单量,看是否存在"月底冲业绩"现象。

复制代码
SELECT
    order_id,
    order_date,
    last_day(order_date) -- 返回该月最后一天,如 2023-10-31
FROM dwd_order_detail
WHERE order_date = last_day(order_date);
2. 月份/周处理

核心函数trunc(date, 'MM')
商业案例:将不同日期的订单归集到对应的"月份桶"中。

复制代码
SELECT
    trunc(order_date, 'MM') as month_group,
    count(*)
FROM dwd_order_detail
GROUP BY trunc(order_date, 'MM');

第三梯队:高阶分析函数(解决"复杂排名与趋势"问题)

这是区分初级和高级分析师的分水岭。

1. 排名函数

核心函数ROW_NUMBER(), RANK(), DENSE_RANK()
区别

  • ROW_NUMBER: 1, 2, 3, 4 (强制排序,无重复)
  • RANK: 1, 2, 2, 4 (跳跃排序,有并列)
  • DENSE_RANK: 1, 2, 2, 3 (不跳跃排序,有并列)

商业案例:Top N 问题(每个品类销量前3的商品)

这是最经典的面试题和业务题。

复制代码
SELECT
    category,
    product_name,
    sales_amt
FROM (
    SELECT
        category,
        product_name,
        sales_amt,
        ROW_NUMBER() OVER(PARTITION BY category ORDER BY sales_amt DESC) as rn
    FROM dws_product_sales
) t
WHERE t.rn <= 3;
2. 偏移分析函数

核心函数LAG(col, n), LEAD(col, n)
应用场景:环比增长、用户行为路径分析、留存。

商业案例:计算每日 GMV 环比增长率

你需要知道今天的销售额比昨天涨了还是跌了。

复制代码
SELECT
    stat_date,
    gmv,
    LAG(gmv, 1) OVER(ORDER BY stat_date) as yesterday_gmv, -- 取上一行的数据
    ROUND(
        (gmv - LAG(gmv, 1) OVER(ORDER BY stat_date)) / LAG(gmv, 1) OVER(ORDER BY stat_date)
    , 2) as growth_rate
FROM ads_daily_gmv;
3. 聚合开窗

核心函数SUM() OVER(...), AVG() OVER(...)
应用场景:计算累计值(如:年初至今销售额)、移动平均线(如:近7天平均活跃用户)。

商业案例:计算"累计销售额"

老板要看截止到每一天的年度累计业绩。

复制代码
SELECT
    stat_date,
    daily_sales,
    SUM(daily_sales) OVER(ORDER BY stat_date) as cumulative_sales -- 从第一行累加到当前行
FROM ads_daily_sales;

第四梯队:复杂数据处理(解决"埋点与日志"问题)

核心函数explode, split, lateral view
应用场景:处理用户搜索词、购物车列表、标签集合。

商业案例:分析用户搜索关键词热度

假设日志表中有一行数据记录了用户一次搜索的多个词:"手机, 华为, 5G"。需要将其拆分为三行进行统计。

复制代码
SELECT
    keyword,
    COUNT(*) as cnt
FROM search_log
LATERAL VIEW explode(split(keywords, ',')) tmp AS keyword -- 将字符串按逗号分割并炸开
GROUP BY keyword;

实战训练题(建议动手写)

为了巩固这些知识,我为你设计了三道从易到难的训练题。你可以尝试自己写 SQL,或者在脑海中构思逻辑。

题目一:连续登录问题(经典留存)

场景 :有一张用户登录表 user_login (user_id, login_date)。
问题 :找出所有连续登录 3 天及以上 的用户。
提示

  1. 先去重(一天登录多次算一次)。
  2. 使用 ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY login_date) 生成序号。
  3. 利用"日期"减去"序号",如果结果相同,说明是连续的(这是著名的 date_sub 解法)。
题目二:漏斗分析(路径转化)

场景 :电商购物行为表 user_action (user_id, action_type, action_time)。action_type 包括 'view' (浏览), 'cart' (加购), 'buy' (购买)。
问题 :计算"浏览 -> 加购 -> 购买"的转化率。即:有多少人浏览了,其中多少人加了购物车,其中多少人买了。
提示

  1. 需要按 user_id 分组。
  2. 利用 MAX(CASE WHEN ...) 标记该用户当天是否发生过某行为。
  3. 统计各行为发生的人数,进行除法计算。
题目三:分组 Top N 与去重(综合)

场景 :订单表 orders (order_id, user_id, category, pay_amount, pay_time)。
问题 :统计2023年10月 ,每个品类下支付金额最高的前2名 用户。
提示

  1. WHERE 过滤时间。
  2. GROUP BY category, user_id 计算每个用户在每个品类的总支付金额。
  3. 使用子查询或 CTE (WITH 语句)。
  4. 外层使用 DENSE_RANK() OVER(PARTITION BY category ORDER BY sum_amt DESC)
  5. 最外层 WHERE rank <= 2

你可以先尝试思考一下这几道题的逻辑,如果有具体的 SQL 写法想要验证,随时发给我,我帮你 Code Review!

相关推荐
2401_846339561 小时前
如何防止邮件HTML被过滤_安全标签白名单【指南】
jvm·数据库·python
_376271531 小时前
怎样查询不同表的字段差异 information_schema结构对比
jvm·数据库·python
weixin_444012931 小时前
宝塔面板如何实现网站重定向_配置301永久跳转与域名更换
jvm·数据库·python
m0_733565461 小时前
CSS如何高效命名样式类_掌握BEM规范提升语义化程度
jvm·数据库·python
woxihuan1234561 小时前
CSS如何引入自适应图标_利用svg外链配合css控制颜色
jvm·数据库·python
2401_880071401 小时前
如何正确合并多个 Word 文档(.docx)并保留格式与分页
jvm·数据库·python
wang3zc1 小时前
MySQL行锁升级为表锁的原因是什么_分析非索引字段查询影响
jvm·数据库·python
2403_883261091 小时前
CSS如何制作简单的加载转圈动画_使用keyframe与animation
jvm·数据库·python
m0_740653221 小时前
c++ 逆向工程ida pro c++如何使用ida pro插件和脚本
jvm·数据库·python