SQL专项练习第二天

        在数据处理和分析中,Hive 是一个强大的工具。本文将通过五个 Hive 相关的问题展示其在不同场景下的应用技巧。

        先在home文件夹下建一个hivedata文件夹,把我们所需的数据写成txt文件导入到/home/hivedata/文件夹下面。

一、找出连续活跃 3 天及以上的用户

问题描述:给定一个用户活跃表t_useractive,包含用户 ID(uid)和活跃时间(dt),要求找出连续活跃 3 天及以上的用户。

解决方案:

  1. 首先使用date_format函数将dt中的日期提取出来,然后按用户 ID 和日期进行分组。
  2. 接着使用窗口函数row_number()date_sub函数计算一个临时列tempdt,用于判断连续日期。
  3. 最后按用户 ID 和tempdt分组,统计数量大于等于 3 的用户 ID。
-- 建表
create table t_useractive(uid   string,dt    string
);
-- 导入数据insert into t_useractive
values('A','2023-10-01'),('A','2023-10-02'),('A','2023-10-03'),('A','2023-10-04'),('B','2023-10-01'),('B','2023-10-03'),('B','2023-10-04'),('B','2023-10-05'),('C','2023-10-01'),('C','2023-10-03'),('C','2023-10-05'),('C','2023-10-06'),('D','2023-10-02'),('D','2023-10-03'),('D','2023-10-05'),('D','2023-10-06');

代码如下:

with t as (select uid, date_format(dt, 'yyyy-MM-dd') dt from t_useractive group by uid, date_format(dt, 'yyyy-MM-dd')
), t2 as(select *, date_sub(dt, row_number() over (partition by uid order by dt )) tempdt from t
) select uid from t2 group by uid, tempdt having count(1) >= 3;

二、统计每月会员数量

创建表和导入数据

[root@hadoop11 data]# cat consumer.txt
1,2021-01-01,2022-01-01
2,2021-02-02,2022-02-02
3,2021-03-03,2022-03-03create table t_consumer(consumerid  string,startdate   string,enddate     string
)row format delimited fields terminated by ',';load data local inpath '/home/hivedata/consumer.txt' into table  t_consumer;

添加依赖和自定义 UDTF

依赖

<dependency><groupId>org.apache.hive</groupId><artifactId>hive-exec</artifactId><version>3.1.2</version>
</dependency>

自定义UDTF

package com.bigdata;import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;import java.util.ArrayList;
import java.util.List;// 这个类是hive 自定义函数类
public class DateExplodeDemo extends GenericUDTF {// 定义函数的返回值名称以及数据类型@Overridepublic StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {// 返回值的数据类型和名称//1.定义输出数据的列名和类型List<String> fieldNames = new ArrayList<String>();List<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();//2.添加输出数据的列名和类型fieldNames.add("mt");fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);}public void process(Object[] args) throws  HiveException {String beginDate = args[0].toString();String endDate = args[1].toString();// 调用之前的方法,返回一个日期列表List<String> dateList = DateUtils.getDateList(beginDate, endDate);for(String date : dateList){forward(new String[]{date});}}@Overridepublic void close() throws HiveException {}
}
package com.bigdata;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;public class DateUtils {/***  给定一个开始和结束日期,返回一个日期列表* @param beginDate  2021/1/1* @param endDate    2022/1/1*                   Jan-21* @return*/public static  List<String> getDateList(String beginDate, String endDate) {// 返回值列表,中间存储日期List<String> list = new ArrayList<String>();// 解析传递过来的日期的格式SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM");// 将Date类型转换为字符串类型,前面是月份,后面是年份SimpleDateFormat sdf = new SimpleDateFormat("MMM-yyyy", Locale.ENGLISH);try {// 将传递过来的日期转换为Date类型Date dateFrom = simpleDateFormat.parse(beginDate);Date dateTo = simpleDateFormat.parse(endDate);// 因为需要用到Calendar 中的 获取下一个月的日期的函数Calendar calendar = Calendar.getInstance();calendar.setTime(dateFrom);// 判断结束日期是否大于开始日期while (dateTo.after(calendar.getTime())) {// 将一个日期转为  月份-年份String yearMonth = sdf.format(calendar.getTime());System.out.println(yearMonth);list.add(yearMonth);calendar.add(Calendar.MONTH,1);}} catch (ParseException e) {throw new RuntimeException(e);}// list中存放的是月份-年份return list;}public static void main(String[] args) {System.out.println(getDateList("2021/1/1","2022/1/1"));}
}

打 jar 包并在 Hive 中使用

add jar /opt/installs/hive/lib/MyFunction-1.0-SNAPSHOT.jar;
create temporary function k1 as 'com.bigdata.DateExlode';

编写 SQL 统计每月会员数量

select mt,count(*) c1
from(select consumerid,mt from t_consumer lateral view k1(startdate,enddate) t1 as mt
)t2 group by mt

假如需要变为以上带有英文的输出,可以使用如下 SQL

selectconcat(case split(mt,'-')[1] when '01' then 'Jan'when '01' then 'Jan'when '02' then 'Feb'when '03' then 'Mar'when '04' then 'Apr'when '05' then 'May'when '06' then 'Jun'when '07' then 'Jul'when '08' then 'Aug'when '09' then 'Sept'when '10' then 'Oct'when '11' then 'Nov'when '12' then 'Dec'end, '-', substr(mt,3,2)), count(1) from t_consumer lateral view k1(startdate,enddate) t as  mt group by mt ;

假如以上结果需要按照日期排序

可以使用如下方式,造出来一个这样的表:

select * from huiyuan order bysplit(dt,'-')[1] ,case split(dt,'-')[0]when 'Jan' then 1when 'Feb' then 2when 'Mar' then 3when 'Apr' then 4when 'May' then 5when 'Jun' then 6when 'Jul' then 7when 'Aug' then 8when 'Sept' then 9when 'Oct' then 10when 'Nov' then 11when 'Dec' then 12 end;

三、统计每个 Top3 歌单以及 Top3 歌单下的 Top3 歌曲

问题描述:有一个听歌流水表songs,存储了用户听歌单歌曲的记录,要求统计每个 Top3 歌单以及 Top3 歌单下的 Top3 歌曲。

解决方案:

  1. 首先找到排名前三的歌单,通过对歌单 ID(lid)进行分组计数,然后使用窗口函数dense_rank()进行排名。
  2. 接着根据排名前三的歌单 ID,统计每个歌单下的歌曲播放次数,并再次使用窗口函数dense_rank()进行排名。
  3. 最后选择排名前三的歌曲。

数据:

用户编号  歌单编号  歌单名称    歌曲编号    歌曲名称
1   1  经典老歌    1   月亮代表我的心
2   1  经典老歌    1   月亮代表我的心
3   1  经典老歌    3   夜来香
4   1  经典老歌    4   我只在乎你
5   1  经典老歌    5   千言万语
6   1  经典老歌    5   千言万语
7   2  流行金曲    7   突然好想你
8   2  流行金曲    8   后来
9   2  流行金曲    9   童话
10  2  流行金曲    10  晴天
11  2  流行金曲    7   突然好想你
12  2  流行金曲    7   突然好想你
13  3  纯音乐集    13  二泉映月
14  3  纯音乐集    14  琵琶语
15  3  纯音乐集    15  梦回还
16  4  欧美音乐    16  Shape of My Heart
17  4  欧美音乐    17  Just the Way You Are
18  4  欧美音乐    18  Hello
19  4  欧美音乐    19  A Thousand Years
20  4  欧美音乐    20  Thinking Out Loud
21  4  欧美音乐    20  Thinking Out Loud
22  4  欧美音乐    18  Hello
23  4  欧美音乐    18  Hello
24  5  民谣时光    24  易燃易爆炸
25  5  民谣时光    25  成全
26  5  民谣时光    25  成全
27  5  民谣时光    25  成全

建表 

-- 创建表
create table song(uid int,pid int,pname string,sid int,sname string
)row format delimited
fields terminated by ' '
tblproperties("skip.header.line.count"="1");
-- 导入数据
load data local inpath '/home/hivedata/songs.txt' into table song;

代码如下:

-- 先找到 top3 歌单
with t as (select lid,count(1) num from songs group by lid
),
t2 as (
select *,dense_rank() over (order by num desc) xh from t
) select lid from t2 where xh <=3;
-- 根据 top3 歌单的数据进行排序,取前三名
with t as (select lid,count(1) num from songs group by lid
),
t2 as (
select *,dense_rank()over (order by num desc) xh from t
),
t3 as(
select lid from t2 where xh <=3
),t4 as (select distinct list_name,song_name,count(1) over(partition by song_name ) cs  from songs where lid in (select lid from t3)
),t5 as (select *,dense_rank() over (partition by list_name order by cs desc) xh from t4
)
select list_name,song_name from t5 where xh <=3;

四、用一条 SQL 语句查询出每门课都大于 80 分的学生姓名

问题描述:给定一个学生成绩表t1,包含学生姓名(name)、课程名称(course)和成绩(grade),要求查询出每门课都大于 80 分的学生姓名。

解决方案:

使用group byhaving子句,先按学生姓名分组,然后计算每个学生的最低成绩,最后筛选出最低成绩大于等于 80 分的学生姓名。

建表:

-- 建表
create table t1(name   string,course string,grade  int
);
-- 导入数据
INSERT INTO t1 (name, course, grade) VALUES
('张三', '英语', 85),
('张三', '语文', 90),
('张三', '数学', 92),
('李四', '英语', 75),
('李四', '语文', 98),
('李四', '数学', 72),
('王五', '英语', 90),
('王五', '语文', 85),
('王五', '数学', 92),
('王五', '体育', 80);

代码如下:

select sc.name from (select t1.name,sum(case  when t1.course='英语' then t1.grade else 0 end) english,sum(case  when t1.course='语文' then t1.grade else 0 end) chinese,sum(case  when t1.course='数学' then t1.grade else 0 end) math,sum(case  when t1.course='体育' then t1.grade else 0 end) pe
from t1 group by name) scwhere english >=80 and chinese >=80 and math >= 80 and pe >= 80
group by name;

假如不考虑没考试的课

select name,min(grade) minScore from t1 group by name having minScore >=80;

五、连续出现的数字

问题描述:有一个表Logs,包含 ID(id)和数字(num),要求查找所有至少连续出现三次的数字。

解决方案:

方案一:
  1. 使用窗口函数row_number()date_sub函数计算一个临时列jyl,用于判断连续数字。
  2. jylnum分组,统计数量大于等于 3 的数字。
方案二:
  1. 使用自连接,连接条件为l1.id = l2.id+1l2.id = l3.id + 1l1.num = l2.numl2.num = l3.num

建表:

-- 建表
create table logs(id int,num string
)row format delimited
fields terminated by ' ';-- 导入数据
load data local inpath '/home/hivedata/logs.txt' into table logs;

代码如下:

-- 方案一
with t as (select *, row_number() over (partition by num order by id ),id - row_number() over (partition by num order by id) jyl from logs
) select num, count(1) from t group by jyl, num having count(1) >= 3;
-- 方案二
select l1.num from logs l1, logs l2, logs l3where l3.id = l2.id+1 and l2.id = l1.id+1 and l1.num = l2.num and l2.num = l3.num;

        通过以上五个问题的解决,展示了 Hive 在数据处理和分析中的强大功能和灵活性。无论是找出连续活跃的用户、统计会员数量、分析歌单数据、筛选学生成绩还是查找连续出现的数字,Hive 都能提供高效的解决方案。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

茄子病虫害数据集。四类:果肉腐烂、蛀虫、健康、黄斑病。4000张图片,已经按照8:2的比例划分好训练集、验证集 txt格式 含类别yaml文件 已经标注好

茄子病虫害数据集。可用于筛选茄子品质、质量&#xff0c;训练采摘机器人视觉算法模型……数据集大部分图片来源于真实果园拍摄的图片&#xff08;生长在果树之上的&#xff09;&#xff0c;图片分辨率高&#xff0c;数据集分为四类&#xff1a;果肉腐烂、蛀虫、健康、黄斑病。…

Pandas数据分析基础

目录标题 Pandas读取和写入数据数据读取读取csv读取excel数据输出 Pandas基础操作索引数据信息统计计算位置计算数据选择 Pandas高级操作复杂查询类型转换数据排序添加修改高级过滤数据迭代高阶函数 Pandas读取和写入数据 Pandas将数据加载到DataFrame后&#xff0c;就可以使用…

算法知识点————贪心

贪心&#xff1a;只考虑局部最优解&#xff0c;不考虑全部最优解。有时候得不到最优解。 DP&#xff1a;考虑全局最优解。DP的特点&#xff1a;无后效性&#xff08;正在求解的时候不关心前面的解是怎么求的&#xff09;&#xff1b; 二者都是在求最优解的&#xff0c;都有最优…

TB6612电机驱动模块(STM32)

目录 一、介绍 二、模块原理 1.原理图 2.电机驱动原理 三、程序设计 main.c文件 Motor.h文件 Motor.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 TB6612FNG 是东芝半导体公司生产的一款直流电机驱动器件&#xff0c;它具有大电流 MOSFET-H 桥结构&#xff…

【每天学个新注解】Day 15 Lombok注解简解(十四)—@UtilityClass、@Helper

UtilityClass 生成工具类的注解 将一个类通过注解变成一个工具类&#xff0c;并没有什么用&#xff0c;本来代码中的工具类数量就极为有限&#xff0c;并不能达到减少重复代码的目的 1、如何使用 加在需要委托将其变为工具类的普通类上。 2、代码示例 例&#xff1a; Uti…

(C语言贪吃蛇)9.贪吃蛇撞墙找死

目录 游戏说明​ 1.撞墙死翘翘的情况 2.如何解决初始化问题 封装函数initSnake(); 注意事项 解决方法 总结 效果演示 游戏说明 玩家通过上下左右按键来控制小蛇的移动&#xff0c;我们之前的内容完成了小蛇每按下一次右键小蛇便向右移动一格&#xff0c;但是玩贪吃蛇一…

vue-live2d看板娘集成方案设计使用教程

文章目录 前言v1.1.x版本&#xff1a;vue集成看板娘&#xff08;暂不使用&#xff0c;在v1.2.x已替换&#xff09;集成看板娘实现看板娘拖拽效果方案资源备份存储 当前最新调研&#xff1a;2024.10.2开源方案1&#xff1a;OhMyLive2D&#xff08;推荐&#xff09;开源方案2&…

Spring Boot中线程池使用

说明&#xff1a;在一些场景&#xff0c;如导入数据&#xff0c;批量插入数据库&#xff0c;使用常规方法&#xff0c;需要等待较长时间&#xff0c;而使用线程池可以提高效率。本文介绍如何在Spring Boot中使用线程池来批量插入数据。 搭建环境 首先&#xff0c;创建一个Spr…

Agent 概念学习

Agent 概念学习 什么是 Agent OpenAI的研究员 Lilian 写过一篇博客:《 LLM Powered Autonomous Agents》&#xff0c;将 Agents 定义为&#xff1a;LLM memory planning skills tool use&#xff0c;即大语言模型、记忆、任务规划、工具使用的集合。 Overview of a LLM-…

多模态—图文匹配

可能最近大家已经发现了chatgpt可以根据自己的描述生成图片&#xff0c;其实这就是一个图文匹配的问题&#xff0c;可以理解为这是一个多模态的问题。 在模型训练时我们需要N个图片和N个文本对进行训练&#xff0c;文本通过text encoder形成文本语义向量&#xff0c;text enco…

930/105每日一题

算法 1 4,2,9,11, 4, 2,4 2,4,9 42 4 24 9 2&#xff08;0&#xff09; 4&#xff08;1&#xff09; 9&#xff08;2&#xff09; 11&#xff08;3&#xff09; 11&#xff08;0&#xff09;11&#xff08;1&#xff09; 9&#xff08;2&#xff09; 11&#xff08;3&#xf…

C++之多态篇(超详细版)

1.多态概念 多态就是多种形态&#xff0c;表示去完成某个行为时&#xff0c;当不同的人去完成时会有不同的形态&#xff0c;举个例子在车站买票&#xff0c;可以分为学生票&#xff0c;普通票&#xff0c;军人票&#xff0c;每种票的价格是不一样的&#xff0c;当你是不同的身…

C语言 | Leetcode C语言题解之第457题环形数组是否存在循环

题目&#xff1a; 题解&#xff1a; int next(int* nums, int numsSize, int cur) {return ((cur nums[cur]) % numsSize numsSize) % numsSize; // 保证返回值在 [0,n) 中 }bool circularArrayLoop(int* nums, int numsSize) {for (int i 0; i < numsSize; i) {if (!n…

C++ | Leetcode C++题解之第456题132模式

题目&#xff1a; 题解&#xff1a; class Solution { public:bool find132pattern(vector<int>& nums) {int n nums.size();vector<int> candidate_i {nums[0]};vector<int> candidate_j {nums[0]};for (int k 1; k < n; k) {auto it_i upper_…

Ubuntu24.04远程开机

近来在几台机器上鼓捣linux桌面&#xff0c;顺便研究一下远程唤醒主机。 本篇介绍Ubuntu系统的远程唤醒&#xff0c;Windows系统的唤醒可搜索相关资料。 依赖 有远程唤醒功能的路由器&#xff08;当前一般都带这个功能&#xff09;有线连接主机&#xff08;无线连接有兴趣朋友…

信息安全工程师(33)访问控制概述

前言 访问控制是信息安全领域中至关重要的一个环节&#xff0c;它提供了一套方法&#xff0c;旨在限制用户对某些信息项或资源的访问权限&#xff0c;从而保护系统和数据的安全。 一、定义与目的 定义&#xff1a;访问控制是给出一套方法&#xff0c;将系统中的所有功能和数据…

【JAVA开源】基于Vue和SpringBoot的宠物咖啡馆平台

本文项目编号 T 064 &#xff0c;文末自助获取源码 \color{red}{T064&#xff0c;文末自助获取源码} T064&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

仿RabbitMQ实现消息队列三种主题的调试及源码

文章目录 开源仓库和项目上线广播交换模式下的测试直接交换模式下的测试主题交换模式下的测试 开源仓库和项目上线 本项目已开源到下面链接下的仓库当中 仿RabbitMQ实现消息队列 广播交换模式下的测试 消费者客户端 在进行不同测试下&#xff0c;消费者客户端只需要改变交换机…

基于SpringBoot+Vue+MySQL的中医院问诊系统

系统展示 用户前台界面 管理员后台界面 医生后台界面 系统背景 随着信息技术的迅猛发展和医疗服务需求的不断增加&#xff0c;传统的中医院问诊流程已经无法满足患者和医院的需求。纸质病历不仅占用大量存储空间&#xff0c;而且容易丢失和损坏&#xff0c;同时难以实现信息的快…

Acwing 背包问题

背包问题 首先&#xff0c;什么是背包问题&#xff1f; 给定N个物品和一个容量为V的背包&#xff0c;每个物品有体积和价值两种属性&#xff0c;在一些限制条件下&#xff0c;将一些物品放入背包&#xff0c;使得在不超过背包体积的情况下&#xff0c;能够得到的最大价值。根据…