HQL 55 题【持续更新】

前言

        今天开始为期一个多月的 HQL 练习,共 55 道 HQL 题,大概每天两道,从初级函数到中级函数。这次的练习不再是基础的 join 那种通用 SQL 语法了,而是引入了更多 Hive 的函数(单行函数、窗口函数等)。  

        我会把 HQL 中函数和语法的一些注意事项写在每一题下面的 "知识点" 中,方便上课复习。同样这博客估计没人看,如果谁实在需要建表语句给我留言就行。

3-10

1、查询累积销量排名第二的商品(中级)

SELECT sku_id from(SELECT sku_id,rank() OVER(ORDER BY order_sum desc) rkfrom(SELECT sku_id,sum(sku_num) order_sumFROM order_detailGROUP BY sku_idORDER BY order_sum descLIMIT 2)as t1)as t2
WHERE rk=2;

知识点:

  • SQL 中 distinct 必须跟在 select 之后
  • distinct 不能单独用于选择性地仅对结果集中的某个字段去重,而不影响其他字段
select distinct sku_id, sku_num,rk from(...
);
-- 尽管查询结果中 sku_id 字段的值可能重复,但是不能通 select distinct 来对单个属性去重
sku_id    sku_num    rk
1            2        1
1            3        2
  • Hive 的子查询必须要有别名 !

3-12

1、筛选2021年总销量小于100的商品(初级)

  • 需求:从订单明细表(order_detail)中筛选出2021年总销量小于100的商品及其销量,假设今天的日期是2022-01-10,不考虑上架时间小于一个月的商品。
  • 思路:拿 2021 年总销量小于100的商品id和上架时间大于30的商品id进行join
order_detail_idorder_idsku_idcreate_datepricesku_num
1112021-09-272000.002
2132021-09-275000.005
3242021-09-286000.009
4252021-09-28500.0033

2.1、查询出2021年总销量小于 100 的商品

-- 1.1 2021年销售总量小于100的商品
select sku_id, sum(sku_num) order_sum
from order_detail
where year(create_date)=2021
group by sku_id
having order_sum<100;

2.2、查询出上架时间大于30天的商品

-- 1.2 上架时间小于 30 天的商品
select sku_id,name from sku_info
where datediff('2022-01-10',from_date)>30;

2.3、join

-- join 两个子表
select t1.sku_id,name from (select sku_id, sum(sku_num) order_sumfrom order_detailwhere year(create_date)=2021group by sku_idhaving order_sum<100)t1 join (select sku_id,name from sku_infowhere datediff('2022-01-10',from_date)>30)t2 on t1.sku_id = t2.sku_id;

知识点

  • datediff('2022-01-10','2021-01-10') = 365,注意:日期1必须大于日期2否则结果是负数

2、查询每日新增用户(初级)

uer_idip_addresslogin_tslogout_ts
101180.149.130.1612021-09-21 08:00:002021-09-27 08:30:00
101180.149.130.1612021-09-27 08:00:002021-09-27 08:30:00
101180.149.130.1612021-09-28 09:00:002021-09-28 09:10:00
101180.149.130.1612021-09-29 13:30:002021-09-29 13:50:00

 思路1:每天有多少人是首日登录就有多少新增用户。查询出每个用户的首日登录时间,然后按照日期分组聚合就得到了每日新增用户。而不是去考虑开窗(我是这么想的)

思路2:开窗也可以实现,用 row_numer 对每个用户的登录时间进行排名(group by user_id),然后根据登录时间进行分区将该天 row_number=1 的值(说明是首次登录)进行聚合。

思路1

2.1、查询用户首日登录日期
-- 查询用户首次登录的日期
select user_id,min(date_format(login_ts,'yyyy-MM-dd')) first_login_date
from user_login_detail
group by user_id;
2.2、查询每天有多少用户是首日登录
-- 按照日期分组得到每天的新增用户
select first_login_date,count(*) from(select user_id,min(date_format(login_ts,'yyyy-MM-dd')) first_login_datefrom user_login_detailgroup by user_id)t1
group by first_login_date;

注意:怎么把 login_ts (格式:2021-09-21 08:00:00)这种时间字符串指定的字段取出来?

我是这么实现的:

select concat_ws('-',string(year(date_format(login_ts,'yyyy-MM-dd HH:mm:ss'))),string(month(date_format(login_ts,'yyyy-MM-dd HH:mm:ss'))),string(day(date_format(login_ts,'yyyy-MM-dd HH:mm:ss')))),

标准:

select date_format(login_ts,'yyyy-MM-dd') from user_login_detail;

思路2

select dt,sum(`if`(rk=1,1,0)) new_user_nums from(select user_id,date_format(login_ts,'yyyy-MM-dd') dt,row_number() over (partition by user_id order by login_ts) rkfrom user_login_detail)t1
group by dt
having new_user_nums>0;

3、用户注册、登录、下单综合统计(初级)

需求:从用户登录明细表(user_login_detail)和订单信息表(order_info)中查询每个用户的注册日期(首次登录日期)、总登录次数,以及2021年的登录次数、订单数和订单总额。

思路:无脑 join 没有什么难度

order_info

序号编号日期金额
11012021-09-2729000.00
21012021-09-2870500.00
31012021-09-2943300.00
41012021-09-30860.00

 user_login_detail

3.1、用户首日登录日期

-- 用户首日登录日期
select user_id,min(date_format(login_ts,'yyyy-MM-dd')) register_date
from user_login_detail 
group by user_id;

注意:能 group by 就 group by 不然 join 之后报错。

3.2、用户累积登录次数

-- 用户累积登录次数
select user_id,size(collect_set(date_format(login_ts,'yyyy-MM-dd'))) total_login_count
from user_login_detail
group by user_id;

知识点: 利用 collect_set() 把登录日期收集到一个集合里,正好做了去重,就不用担心用户一天登录多次的情况了。

3.3、用户2021年登录次数

-- 用户2021登录次数
select user_id,size(collect_set(date_format(login_ts,'yyyy-MM-dd'))) login_count_2021
from user_login_detail
where year(date_format(login_ts,'yyyy-MM-dd'))=2021
group by user_id;

3.4、用户2021年下单次数和下单金额

-- 用户2021年下单次数和下单金额
select user_id,count(order_id) order_count_2021,sum(total_amount) order_amount_2021
from order_info
where year(create_date)=2021
group by user_id,year(create_date);

3.5、join起来

select t1.user_id,register_date,total_login_count,login_count_2021,order_count_2021,order_amount_2021 from(select user_id,min(date_format(login_ts,'yyyy-MM-dd')) register_date from user_login_detail group by user_id)t1 join (select user_id,size(collect_set(date_format(login_ts,'yyyy-MM-dd'))) total_login_countfrom user_login_detailgroup by user_id)t2 on t1.user_id=t2.user_id
join (select user_id,size(collect_set(date_format(login_ts,'yyyy-MM-dd'))) login_count_2021
from user_login_detail
where year(date_format(login_ts,'yyyy-MM-dd'))=2021
group by user_id)t3 on t1.user_id=t3.user_id
join (select user_id,count(order_id) order_count_2021,sum(total_amount) order_amount_2021from order_infowhere year(create_date)=2021group by user_id,year(create_date))t4 on t1.user_id=t4.user_id;

3.13

1、向用户推荐朋友收藏的商品

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

firendship_info

user1_iduser2_id
1011010
101108
101106
101104

favor_info

user_idsku_idcreate_date
10132021-09-23
101122021-09-23
10162021-09-25
101102021-09-21

思路

  • 核心就是 left join ,因为 left join 可以把保留左表的内容(这里我们保留的是好友的商品收藏表),我们只要根据用户喜欢的商品id和好友喜欢的商品id进行 left join ,得到的字段"sku_id"如果不为 null 就说明这件商品他俩都收藏了,如果为 null 就说明这件商品好友收藏了,但是用户没有收藏。

1.1、获取用户所有好友

-- 查询所有用户的好友
select user1_id user_id,user2_id friend_id from friendship_info
union
select user2_id,user1_id from friendship_info;

知识点

  • join 是横向合并,会形成宽表;而 union 是纵向合并,形成长表(union 会对结果进行排序去重,union all 不会)

1.2、得到用户好友的收藏列表

-- join得到用户好友收藏的商品select user1_id user_id,user2_id friend_id from friendship_infounionselect user2_id,user1_id from friendship_infojoin favor_info firend_favoron user2_id=firend_favor.user_id;

1.3、left join 过滤

select distinct t1.user_id,firend_favor.sku_id
from (select user1_id user_id,user2_id friend_id from friendship_infounionselect user2_id,user1_id from friendship_info
)t1join favor_info firend_favoron t1.friend_id=firend_favor.user_idleft join favor_info user_favoron t1.user_id=user_favor.user_id and firend_favor.sku_id=user_favor.sku_idwhere user_favor.sku_id is null;

2、男性和女性每日的购物总金额统计(初级)

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

order_info

user_info

编号性别出生日期
1011990-01-01
1021991-02-01
1031992-03-01
1041993-04-01

思路1

1、获取不同性别的消费信息
select t2.gender,t1.create_date,t1.total_amount
from order_info t1
join user_info t2 on t1.user_id=t2.user_id

 我们没有必要查询用户的 id 信息,只需要性别(后面我们需要根据性别过滤)、创建订单的日期(后面我们需要根据日期分组)和订单总额(我们需要根据不同性别统计每天的订单总额)即可。

2、按照日期 join 不同性别的每天销售总额
select coalesce(t3.create_date,t4.create_date),`if`(t3.total_amount_male is null,0,t3.total_amount_male),`if`(t4.total_amount_female is null ,0,t4.total_amount_female) from(select create_date,sum(total_amount) total_amount_male from(select t2.gender,t1.create_date,t1.total_amountfrom order_info t1join user_info t2 on t1.user_id=t2.user_id)t1where gender='男'group by create_date)t3 full join (select create_date,sum(total_amount) total_amount_female from(select t2.gender,t1.create_date,t1.total_amountfrom order_info t1join user_info t2 on t1.user_id=t2.user_id)t2where gender='女'group by create_date)t4 on t3.create_date=t4.create_date

知识点

  • 显然 t3 和 t4 这两个子表分别是男性和女性的每天购物总额,这里我们进行的是 full join 这样会保留两张表的所有数据,因为数据中存在某 一天男生购物了但是女生没有,或者女士购物了男性没有。
  • 对于最后查询结果的日期字段就需要保证这个日期不能为 null,但是我们又不能显示 t3 t4 两个日期,所以我们使用了 coalesce 字段来获取非 null 的日期字段(前后顺序并不影响)
  • COALESCE 函数用于返回多个表达式中的第一个非NULL值。

思路2

思路1是我自己实现的一种方式,思路2是答案,不得不说还是这种写法高级:

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

知识点

  • cast(expr as <type>):将expr的执行结果转换为<type>类型的数据并返回,expr可以是函数(可以嵌套)、字段或字面值。转换失败返回null,对于cast(expr as boolean),对任意的非空字符串expr返回true

  • decimal(精度,标度):比如 decimal(16,2)表示一个十进制数,其中16是总的数字数量(精度),而2是小数点后的数字数量(标度)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/748205.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

双线性插值缩放算法原理以及matlab与verilog的实现(二)

系列文章目录 双线性插值缩放算法原理以及matlab与verilog的实现&#xff08;一&#xff09; 文章目录 系列文章目录前言一、前提回顾二、FPGA实现步骤2.1 找到源图像四个像素点求目标像素点2.2 FPGA实现步骤2.3 总体框架2.4 ROM缓存模块2.5 VGA模块2.6 双线性算法模块 三、下…

mysql实战开发之 mysql 删除一张表某个字段的sql语句

有一张表, 我需要删除这张表其中的某一个或者某几个字段, 相信大家在日常开发中应该会遇到这种情况, 然后刚好自己接触的项目安装的mysql关闭了允许远程连接的设置, 也就是说不允许使用类似于navicat 等可视化工具连接, 那么就没办法通过可视化工具直接去通过鼠标操作就可以 完…

Lua 学习

参照 注释 -- 这是单行注释--[[这是多行注释--]]if语句 if true thenprint(true) endif else语句 nil是false if nil thenprint("nil被当作true处理") elseprint("nil被当作false处理") end运算符 % 取余 ^ 乘幂 A10,A^2100 // 整除运算符&#xff0…

【 JS 】闭包

“在黑暗的时刻&#xff0c;不要忘记你内心的光芒&#xff0c;它将指引你找到前进的方向&#xff0c;迈向胜利的辉煌。” 定义 MDN 对闭包的定义为&#xff1a; 闭包是指那些能够访问自由变量的函数。 那什么是自由变量呢&#xff1f; 自由变量是指在函数中使用的&#xff0c;…

linux系统docker容器的容器卷

容器卷 容器卷宿主机和容器之间映射添加容器卷读写规则映射添加卷的继承和共享 容器卷 挂载容器卷加上--privileged参数避免权限原因报错 --privilegedturn //开启权限Docker挂载主机目录访问如果出现cannot open directory .: Permission denied 解决办法&#xf…

【MySQL 系列】MySQL 语句篇_DDL 语句

DDL&#xff08; Data Definition Language&#xff0c;数据定义语言&#xff09;用在定义或改变表的结构数据类型、表之间的链接和约束等初始化工作上。常用的语句关键字包括 CREATE、 DROP、 ALTER 等。 文章目录 1、MySQL 中的 DQL 语句2、MySQL 中库表的 DQL 语句详解2.1、…

【大数据面试题】014 Flink CDC 用过吗,请简要描述

一步一个脚印&#xff0c;一天一道面试题。 完成比完美更重要&#xff0c;明天更新完&#xff01; Flink CDC 的诞生背景 Flink CDC 的全称是 Change Data Capture&#xff08;变更数据捕获&#xff09; 每一项技术的诞生都是为了解决某个问题&#xff0c;某个痛点。而 Flink…

【算法与数据结构】深入解析二叉树(二)之堆结构实现

文章目录 &#x1f4dd;二叉树的顺序结构及实现&#x1f320; 二叉树的顺序结构&#x1f320; 堆的实现&#x1f320; 堆的实现&#x1f309;堆向下调整算法&#x1f309;堆的创建&#x1f309;建堆时间复杂度&#x1f309;堆的插入&#x1f309;堆的删除 &#x1f320;堆向上调…

mysql判断指定字符串在字符串中是否存在

相关函数有&#xff1a;locate、FIND_IN_SET。这两者都可以用来在字符串中查找子串&#xff0c;均为两个参数。 LOCATE&#xff1a;主要是针对普通的字符串查找&#xff0c;参数1在参数2中是否存在&#xff0c;若存在则返回首次出现的索引位置&#xff08;第一个位置索引为1&am…

详细分析Java中Stream流和for循环的差异之处

目录 前言1. 基本知识2. Demo 前言 事情起因是遍历大数据的时候&#xff0c;数据卡顿很严重 对于Java的基本知识推荐阅读&#xff1a;java框架 零基础从入门到精通的学习路线 附开源项目面经等&#xff08;超全&#xff09; 1. 基本知识 在Java中&#xff0c;Stream API提供…

dockers拉取MySQL及Redis并挂载文件

目录 一 . MySQL拉取 1、进入 MySQL 容器内部。 2、登录 MySQL。 3、修改远程连接 4、刷新 二 . Redis拉取 1 . redis/conf中新建文件redis.conf&#xff0c;内容如下&#xff1a; 2 . 容器运行 一 . MySQL拉取 docker run -d --restartalways --name mysql \ -v /…

hive逗号分割行列转换

select * from ( select back_receipt_nos,order_no,reject_no from ods_one.ods_us_wms_reject_order_match_all_d where order_no 10150501385980001 ) t1 lateral view explode(split(t1.back_receipt_nos, ,)) t as back_receipt_no where 1 1;

19 OpenCV 霍夫曼变换检测圆

文章目录 cv::HoughCircles算子参数示例 cv::HoughCircles 因为霍夫圆检测对噪声比较敏感&#xff0c;所以首先要对图像做中值滤波。 基于效率考虑&#xff0c;Opencv中实现的霍夫变换圆检测是基于图像梯度的实现&#xff0c;分为两步&#xff1a; 检测边缘&#xff0c;发现可能…

2024年AI辅助研发趋势深度解析:科技革新与效率提升的双重奏

随着人工智能技术的迅猛发展&#xff0c;AI辅助研发正逐渐成为科技界和工业界的热门话题。特别是在2024年&#xff0c;这一趋势将更加明显&#xff0c;AI辅助研发将在各个领域展现出强大的潜力和应用价值。 首先&#xff0c;AI辅助研发将进一步提升研发效率。传统的研发模式往…

Day43-2-企业级实时复制intofy介绍及实践

Day43-2-企业级实时复制intofy介绍及实践 1. 企业级备份方案介绍1.1 利用定时方式&#xff0c;实现周期备份重要数据信息。1.2 实时数据备份方案1.3 实时复制环境准备1.4 实时复制软件介绍1.5 实时复制inotify机制介绍1.6 项目部署实施1.6.1 部署环境准备1.6.2 检查Linux系统支…

中电金信:技术实践|Flink维度表关联方案解析

导语&#xff1a;Flink是一个对有界和无界数据流进行状态计算的分布式处理引擎和框架&#xff0c;主要用来处理流式数据。它既可以处理有界的批量数据集&#xff0c;也可以处理无界的实时流数据&#xff0c;为批处理和流处理提供了统一编程模型。 维度表可以看作是用户来分析数…

JavaScript进阶:js的一些学习笔记-this指向,call,apply,bind,防抖,节流

文章目录 1. this指向1. 箭头函数 this的指向 2. 改变this的指向1. call()2. apply()3. bind() 3. 防抖和节流1. 防抖2. 节流 1. this指向 1. 箭头函数 this的指向 箭头函数默认帮我们绑定外层this的值&#xff0c;所以在箭头函数中this的值和外层的this是一样的箭头函数中的…

Pytorch nn.Module

一、torch.nn简介 torch.nn是 PyTorch 中用于构建神经网络的模块。它提供了一系列的类和函数&#xff0c;用于定义神经网络的各种层、损失函数、优化器等。 torch.nn提供的类&#xff1a; Module: 所有神经网络模型的基类&#xff0c;用于定义自定义神经网络模型。Linear: 线…

Spring-1

目录 概念 优点 Autowired和Resource关键字 相同点 不同点 依赖注入的三种方式 概念 Spring 是个java企业级应用的开源开发框架。Spring主要用来开发Java应用&#xff0c;但是有些扩展是针对构建J2EE&#xff08;Java平台企业版&#xff09;平台的web应用。Spring 框架目…

前端算法 - 面试记录

1. 实现两个字符串相加&#xff08;不能直接转成数字使用加法运算&#xff0c;因为js精度规定不能超出一定长度&#xff09; 现场写法完善&#xff1a; function addStr(a, b) {let res let j 0const add (x, y) > {let numif (x y > 10) {num x y j - 10j 1}e…