大数据技术之Hive SQL题库-中级4

简介: 大数据技术之Hive SQL题库-中级4

2.13 即时订单比例

2.13.1 题目需求

订单配送中,如果期望配送日期和下单日期相同,称为即时订单,如果期望配送日期和下单日期不同,称为计划订单。

请从配送信息表(delivery_info)中求出每个用户的首单(用户的第一个订单)中即时订单的比例,保留两位小数,以小数形式显示。期望结果如下:

percentage

0.6

2.13.2 代码实现

hive>

select
    round(sum(if(order_date=custom_date,1,0))/count(*),2) percentage
from
(
    select
        delivery_id,
        user_id,
        order_date,
        custom_date,
        row_number() over (partition by user_id order by order_date) rn
    from delivery_info
)t1
where rn=1;


骚戴理解:还是那句话,摆脱mysql的惯有思维!也就是使用传统的group by来实现的都优先考虑窗口函数,round(sum(if(order_date=custom_date,1,0))/count(*),2)我一开始想的就是用where来实现,但是round(sum(if(order_date=custom_date,1,0))/count(*),2)这样写要容易很多,简洁很多!


需要用到的表:delivery_info表

*2.14 向用户推荐朋友收藏的商品

2.14.1 题目需求

现需要请向所有用户推荐其朋友收藏但是用户自己未收藏的商品,请从好友关系表(friendship_info)和收藏表(favor_info)中查询出应向哪位用户推荐哪些商品。期望结果如下:

1)部分结果展示

user_id(用户id)

sku_id(应向该用户推荐的商品id)

101

2

101

4

101

7

101

9

101

8

101

11

101

1


2)完整结果

user_id sku_id


101 2


101 4


101 7


101 9


101 8


101 11


101 1


102 3


102 5


102 10


103 2


103 1


103 9


104 1


104 4


104 10


104 5


104 2


105 1


105 2


105 6


105 12


105 3


106 11


106 10


106 8


106 9


106 3


107 11


107 7


107 4


107 9


107 12


107 1


107 8


107 6


107 2


108 2


108 6


108 12


108 1


108 7


108 4


108 5


109 6


109 10


109 7


109 1


109 12


109 3


109 11


1010 4


1010 10


1010 6


1010 12


1010 11


1010 8


1010 3


1010 5


1010 7


2.14.2 代码实现

hive>

select
    distinct t1.user_id,
    friend_favor.sku_id
from
(
    select
        user1_id user_id,
        user2_id friend_id
    from friendship_info
    union
    select
        user2_id,
        user1_id
    from friendship_info
)t1
left join favor_info friend_favor
on t1.friend_id=friend_favor.user_id
left join favor_info user_favor
on t1.user_id=user_favor.user_id
and friend_favor.sku_id=user_favor.sku_id
where user_favor.sku_id is null;

2.15 查询所有用户的连续登录两天及以上的日期区间

2.15.1 题目需求

从登录明细表(user_login_detail)中查询出,所有用户的连续登录两天及以上的日期区间,以登录时间(login_ts)为准。期望结果如下:

user_id(用户id)

start_date(开始日期)

end_date(结束日期)

101

2021-09-27

2021-09-30

102

2021-10-01

2021-10-02

106

2021-10-04

2021-10-05

107

2021-10-05

2021-10-06


2.15.2 代码实现

hive>

select user_id,
       min(login_date) start_date,
       max(login_date) end_date
from (
         select user_id,
                login_date,
                date_sub(login_date, rn) flag
         from (
                  select user_id,
                         login_date,
                         row_number() over (partition by user_id order by login_date) rn
                  from (
                           select user_id,
                                  date_format(login_ts, 'yyyy-MM-dd') login_date
                           from user_login_detail
                           group by user_id, date_format(login_ts, 'yyyy-MM-dd')
                       ) t1
              ) t2
     ) t3
group by user_id, flag
having count(*) >= 2;
骚戴解法
SELECT 
    user_id ,
    min(date_format(login_ts,'yyyy-MM-dd')) start_date,
    max(date_format(login_ts,'yyyy-MM-dd')) end_date
FROM (
SELECT 
    user_id ,
    login_ts ,
    row_number() over(PARTITION by user_id order by login_ts) rn,
    date_sub(login_ts,row_number() over(PARTITION by user_id order by login_ts)) flag
FROM user_login_detail
)t 
GROUP BY user_id ,flag
HAVING count(flag) >1

骚戴理解:这个题目在消化了第二题后,就可以做出来了,突然就不难了哈哈,以下是需要用到的表


2.16 男性和女性每日的购物总金额统计

2.16.1 题目需求

从订单信息表(order_info)和用户信息表(user_info)中,分别统计每天男性和女性用户的订单总金额,如果当天男性或者女性没有购物,则统计结果为0。期望结果如下:

1686568339835.png

2.16.2 代码实现

hive>

select create_date,
       sum(if(gender = '男', total_amount, 0)) total_amount_male,
       sum(if(gender = '女', total_amount, 0)) total_amount_female
from order_info oi
         left join
     user_info ui
     on oi.user_id = ui.user_id
group by create_date;

骚戴理解:这题目不难,我没有摆脱惯性思维,没想到用sum(if(gender = '男', total_amount, 0)),理一下思路,首先左连接--->根据下单日期分组--->通过if函数判断是男是女--->sum来统计总数


所需要的两个表:order_info表和user_info表


*2.17 订单金额趋势分析

2.17.1 题目需求

查询截止每天的最近3天内的订单金额总和以及订单金额日平均值,保留两位小数,四舍五入。期望结果如下:

1686568386408.png


2.17.2 代码实现

hive>

select create_date,
       round(sum(total_amount_by_day) over (order by create_date rows between 2 preceding and current row ),2) total_3d,
       round(avg(total_amount_by_day) over (order by create_date rows between 2 preceding and current row ), 2) avg_3d
from (
         select create_date,
                sum(total_amount) total_amount_by_day
         from order_info
         group by create_date
     ) t1;

骚戴理解:这里我理解的近三天是连续的三天,上面的hql是有问题的,它只能统计所有数据都是连续的情况,例如第一条是2020-10-08,他就不是连续的,那么统计的2021-09-27的总数就应该是29000,但它把2020-10-08的数据也加进来了,这是有问题的,平均值也有问题,所以2021-09-27和2021-09-28的总数和平均值都是错的,但是这样的通过行来求近三天内的思路可以学习一下,order by create_date rows between 2 preceding and current row表示按create_date排序,并且获取排序后的前两行到当前行的数据,通过这个来实现“最近3天内”


2.18 购买过商品1和商品2但是没有购买商品3的顾客

2.18.1 题目需求

从订单明细表(order_detail)中查询出所有购买过商品1和商品2,但是没有购买过商品3的用户,期望结果如下:

user_id

103

105


2.18.2 代码实现

hive>

select user_id
from (
         select user_id,
                collect_set(sku_id) skus
         from order_detail od
                  left join
              order_info oi
              on od.order_id = oi.order_id
         group by user_id
     ) t1
where array_contains(skus, '1')
  and array_contains(skus, '2')
  and !array_contains(skus, '3');

骚戴理解:理清思路,把两个表left join并且按用户id分组--->每个用户下单的商品id收集成一个集合--->通过array_contains来判断是否包含对应的商品id


这里两个亮点:collect_set函数的作用是收集并形成set集合,结果去重,这里用sku_id会有重复的,所以要去重,array_contains来判断集合里有没有这个元素,有就返回true


需要用到的表:order_detail表和order_info表


2.19 统计每日商品1和商品2销量的差值

2.19.1 题目需求

从订单明细表(order_detail)中统计每天商品1和商品2销量(件数)的差值(商品1销量-商品2销量),期望结果如下:

1686568456588.png

2.19.2 代码实现

hive>

select create_date,
       sum(if(sku_id = '1', sku_num, 0)) - sum(if(sku_id = '2', sku_num, 0)) diff
from order_detail
where sku_id in ('1', '2')
group by create_date;

骚戴理解:这个题目我一开始是这样写的,但是会报错!

所需要的表:order_detail表

2.20 查询出每个用户的最近三笔订单

2.20.1 题目需求

从订单信息表(order_info)中查询出每个用户的最近三笔订单,期望结果如下:

1686568490399.png

1686568502971.png

1686568519554.png

2.20.2 代码实现

hive>

select user_id,
       order_id,
       create_date
from (
         select user_id
              , order_id
              , create_date
              , row_number() over (partition by user_id order by create_date desc) rk
         from order_info
     ) t1
where rk <= 3;

骚戴理解:“最近三笔订单”是通过排名后求最大的日期的前三天,也就是通过row_number() over (partition by user_id order by create_date desc) rk 和where rk <= 3;来实现


需要用到的表:order_info表



2.21 查询每个用户登录日期的最大空档期

2.21.1 题目需求

从登录明细表(user_login_detail)中查询每个用户两个登录日期(以login_ts为准)之间的最大的空档期。统计最大空档期时,用户最后一次登录至今的空档也要考虑在内,假设今天为2021-10-10。期望结果如下:

1686568559211.png

2.21.2 代码实现

hive>

select
    user_id,
    max(diff) max_diff
from
(
    select
        user_id,
        datediff(next_login_date,login_date) diff
    from
    (
        select
            user_id,
            login_date,
            lead(login_date,1,'2021-10-10') over(partition by user_id order by login_date) next_login_date
        from
        (
            select
                user_id,
                date_format(login_ts,'yyyy-MM-dd') login_date
            from user_login_detail
            group by user_id,date_format(login_ts,'yyyy-MM-dd')
        )t1
    )t2
)t3
group by user_id;

骚戴理解:这个题目有点难度,先理清思路,首先对日期进行格式化并且以用户id和格式化后的日期进行分组--->通过lead() over()函数来查询下一个登录日期--->通过datediff函数求差值--->通过max取最大值


group by user_id,date_format(login_ts,'yyyy-MM-dd')这里分组是因为要去重,因为同一天内同一个用户可能登录多次


lead(login_date,1,'2021-10-10') over(partition by user_id order by login_date) 是核心,用来实现求下一次的日期,这个语句要从后往前看,先看over(partition by user_id order by login_date) 这个无非就是分组加排序,并不陌生,值得一提的是这个partition by有时候可以不写!然后再看lead(login_date,1,'2021-10-10')的意思是求login_date的下一次的日期,如果没有下一次就用2021-10-10来作为下一次日期,例如下面红色画出来的部分

  1. 这个题目我一开始是这样写的


我一开始想用date_sub函数来求两个日期只差,但是报错

可以看出这个date_sub函数不能用于string类型的日期,当然它这个日期设置为string也不合理,至于这各报错为什么显示的是date_add函数我也不知道,然后我使用datediff函数就可以了


我一开始没有写最后的这个group by user_id,然后报错如下


这里报语法错误是因为select后面用到了max函数,所以必须分组!而且从语义来讲也要分组,因为会有重复的,如下所示,可以看到101有三条重复的1,所以需要分组!

  1. 需要用到的表:user_login_detail表


相关实践学习
基于MaxCompute的热门话题分析
Apsara Clouder大数据专项技能认证配套课程:基于MaxCompute的热门话题分析
目录
相关文章
|
10月前
|
SQL 数据可视化 关系型数据库
MCP与PolarDB集成技术分析:降低SQL门槛与简化数据可视化流程的机制解析
阿里云PolarDB与MCP协议融合,打造“自然语言即分析”的新范式。通过云原生数据库与标准化AI接口协同,实现零代码、分钟级从数据到可视化洞察,打破技术壁垒,提升分析效率99%,推动企业数据能力普惠化。
820 3
|
SQL 分布式计算 大数据
大数据新视界 --大数据大厂之Hive与大数据融合:构建强大数据仓库实战指南
本文深入介绍 Hive 与大数据融合构建强大数据仓库的实战指南。涵盖 Hive 简介、优势、安装配置、数据处理、性能优化及安全管理等内容,并通过互联网广告和物流行业案例分析,展示其实际应用。具有专业性、可操作性和参考价值。
大数据新视界 --大数据大厂之Hive与大数据融合:构建强大数据仓库实战指南
|
SQL 分布式计算 资源调度
Dataphin功能Tips系列(48)-如何根据Hive SQL/Spark SQL的任务优先级指定YARN资源队列
如何根据Hive SQL/Spark SQL的任务优先级指定YARN资源队列
526 4
|
SQL 存储 关系型数据库
【SQL技术】不同数据库引擎 SQL 优化方案剖析
不同数据库系统(MySQL、PostgreSQL、Doris、Hive)的SQL优化策略。存储引擎特点、SQL执行流程及常见操作(如条件查询、排序、聚合函数)的优化方法。针对各数据库,索引使用、分区裁剪、谓词下推等技术,并提供了具体的SQL示例。通用的SQL调优技巧,如避免使用`COUNT(DISTINCT)`、减少小文件问题、慎重使用`SELECT *`等。通过合理选择和应用这些优化策略,可以显著提升数据库查询性能和系统稳定性。
759 9
|
SQL 存储 算法
比 SQL 快出数量级的大数据计算技术
SQL 是大数据计算中最常用的工具,但在实际应用中,SQL 经常跑得很慢,浪费大量硬件资源。例如,某银行的反洗钱计算在 11 节点的 Vertica 集群上跑了 1.5 小时,而用 SPL 重写后,单机只需 26 秒。类似地,电商漏斗运算和时空碰撞任务在使用 SPL 后,性能也大幅提升。这是因为 SQL 无法写出低复杂度的算法,而 SPL 提供了更强大的数据类型和基础运算,能够实现高效计算。
|
SQL 分布式计算 Hadoop
Hadoop-12-Hive 基本介绍 下载安装配置 MariaDB安装 3台云服务Hadoop集群 架构图 对比SQL HQL
Hadoop-12-Hive 基本介绍 下载安装配置 MariaDB安装 3台云服务Hadoop集群 架构图 对比SQL HQL
442 3
|
SQL 安全 数据库
sql注入技术
sql注入技术
|
SQL 机器学习/深度学习 自然语言处理
Text-to-SQL技术演进 - 阿里云OpenSearch-SQL在BIRD榜单夺冠方法剖析
本文主要介绍了阿里云OpenSearch在Text-to-SQL任务中的最新进展和技术细节。
|
SQL 分布式计算 Java
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
487 0
|
SQL 分布式计算 关系型数据库
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
483 0