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-03

create 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 {

    // 定义函数的返回值名称以及数据类型
    @Override
    public 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});
        }
    }



    @Override
    public 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

select
    concat(
        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 by
    split(dt,'-')[1] ,
    case split(dt,'-')[0]
        when 'Jan' then 1
        when 'Feb' then 2
        when 'Mar' then 3
        when 'Apr' then 4
        when 'May' then 5
        when 'Jun' then 6
        when 'Jul' then 7
        when 'Aug' then 8
        when 'Sept' then 9
        when 'Oct' then 10
        when 'Nov' then 11
        when '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) sc
    where 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 l3
    where l3.id = l2.id+1 and l2.id = l1.id+1 and l1.num = l2.num and l2.num = l3.num;

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AI论文精读1】针对知识密集型NLP任务的检索增强生成(RAG原始论文)

目录 一、简介一句话简介作者、引用数、时间论文地址开源代码地址 二、摘要三、引言四、整体架构&#xff08;用一个例子来阐明&#xff09;场景例子&#xff1a;核心点&#xff1a; 五、方法 &#xff08;架构各部分详解&#xff09;5.1 模型1. RAG-Sequence Model2. RAG-Toke…

Python+Matplotlib创建y=sinx、y=cosx、y=sinx+cosx可视化

y sin x (奇函数)&#xff1a; 图像关于原点对称。 对于任何 x&#xff0c;sin(-x) -sin(x)&#xff0c;符合奇函数定义。 y cos x (偶函数)&#xff1a; 图像关于 y 轴对称。 对于任何 x&#xff0c;cos(-x) cos(x)&#xff0c;符合偶函数定义。 y sin x cos x (既…

安全帽头盔检测数据集 3类 12000张 安全帽数据集 voc yolo

安全帽头盔检测数据集 3类 12000张 安全帽数据集 voc yolo 安全帽头盔检测数据集介绍 数据集名称 安全帽头盔检测数据集 (Safety Helmet and Person Detection Dataset) 数据集概述 该数据集专为训练和评估基于YOLO系列目标检测模型&#xff08;包括YOLOv5、YOLOv6、YOLOv7…

LabVIEW机床加工监控系统

随着制造业的快速发展&#xff0c;机床加工的效率与稳定性成为企业核心竞争力的关键。传统的机床监控方式存在效率低、无法远程监控的问题。为了解决这些问题&#xff0c;开发了一种基于LabVIEW的机床加工监控系统&#xff0c;通过实时监控机床状态&#xff0c;改进生产流程&am…

Spring MVC__入门

目录 一、SpringMVC简介1、什么是MVC2、什么是SpringMVC 二、Spring MVC实现原理2.1核心组件2.2工作流程 三、helloworld1、开发环境2、创建maven工程3、配置web.xml4、创建请求控制器5、创建springMVC的配置文件6、测试HelloWorld7、总结 一、SpringMVC简介 1、什么是MVC MV…

html5 + css3(上)

目录 HTML初识基础认知web标准vscode的简介和使用注释 HTML标签学习排版标签标题和段落换行和水平线标签 文本格式化标签媒体标签图片标签图片-基本使用图片-属性 路径绝对路径相对路径 音频标签视频标签链接标签 HTML基础列表标签列表-无序和有序列表-自定义 表格标签表格-使用…

【JAVA开源】基于Vue和SpringBoot的周边产品销售网站

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

Java网络通信—UDP

0.小记 1.udp通信不需要建立socket管道&#xff0c;一边只管发&#xff0c;一边只管收 2.客户端&#xff1a;将数据&#xff08;byte&#xff09;打包成包裹&#xff08;DatagramPacket&#xff09;&#xff0c;写上地址&#xff08;IP端口&#xff09;&#xff0c;通过快递站&…

【HTML并不简单】笔记1-常用rel总结:nofollow、noopener、opener、noreferrer,relList

文章目录 rel"nofollow"rel"noopener"与rel"opener"rel"noreferrer"relList对象 《HTML并不简单&#xff1a;Web前端开发精进秘籍》张鑫旭&#xff0c;一些摘要&#xff1a; HTML&#xff0c;这门语言的知识体系非常庞杂&#xff0c;涉…

Nagle 算法:优化 TCP 网络中小数据包的传输

1. 前言 在网络通信中&#xff0c;TCP&#xff08;传输控制协议&#xff09;是最常用的协议之一&#xff0c;广泛应用于各种网络应用&#xff0c;如网页浏览、文件传输和在线游戏等。然而&#xff0c;随着互联网的普及&#xff0c;小数据包的频繁传输成为一个不容忽视的问题。…

php email功能实现:详细步骤与配置技巧?

php email发送功能详细教程&#xff1f;如何使用php email服务&#xff1f; 无论是用户注册、密码重置&#xff0c;还是订单确认&#xff0c;电子邮件都是与用户沟通的重要手段。AokSend将详细介绍如何实现php email功能&#xff0c;并提供一些配置技巧&#xff0c;帮助你更好…

spring揭秘25-springmvc03-其他组件(文件上传+拦截器+处理器适配器+异常统一处理)

文章目录 【README】【1】文件上传与MultipartResolver【1.1】使用MultipartResolver进行文件上传【1.2】springmvc处理multipart多部件请求流程【1.3】使用springmvc上传文件代码实现&#xff08;springmvc6.10版本&#xff09;&#xff1a; 【2】Handler与HandlerAdaptor&…

【含文档】基于Springboot+Vue的活力健身馆管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

劳动与科技、艺术结合更好提高劳动教育意义

在中小学教育中&#xff0c;劳动教育是培养学生基本生活技能和劳动习惯的重要环节。但当代的劳动教育不在单纯的劳动&#xff0c;而是劳动技能的提升与学习&#xff0c;通过学习劳动技能与实践活动&#xff0c;强化劳动教育与其他课程的融合&#xff0c;学生深刻理解劳动的意义…

如何在每台设备上恢复已删除的照片

从 PC、智能手机或 USB 闪存驱动器丢失图像可能会让人不知所措。幸运的是&#xff0c;使用最好的照片恢复软件&#xff0c;你可以在Windows和Mac上找回已删除的照片。该博客讨论了如何使用 Photos Recovery 恢复丢失的图像。 数码照片是我们记忆的重要组成部分。但是&#xff…

【自然语言处理】(1) --语言转换方法

文章目录 语言转换方法一、统计语言模型1. 词向量转换2. 统计模型问题 二、神经语言模型1. 词向量化2. 维度灾难3. 解决维度灾难4. embedding词嵌入5. Word2Vec技术5.1 连续词袋模型&#xff08;CBOW&#xff09;5.2 跳字模型&#xff08;Skip-gram&#xff09; 总结 语言转换方…

Vue3中使用axios

Promise介绍 同步代码与异步代码 安装并引入axios npm install axios 此时package.json里面就多了axios依赖 引入axios 获取数据 Axios GET参数构成&#xff1a;axios.get(url,{config{},…{}…}) url: 字符串&#xff1a;目标服务器的地址&#xff0c;如 https://api.examp…

需求6:如何写一个后端接口?

这两天一直在对之前做的工作做梳理总结&#xff0c;不过前两天我都是在总结一些bug的问题。尽管有些bug问题我还没写文章&#xff0c;但是&#xff0c;我今天不得不先停下对bug的总结了。因为在国庆之后&#xff0c;我需要自己开发一个IT资产管理的功能&#xff0c;这个功能需要…

【Redis】如何在 Ubuntu 上安装 Redis 5

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 本期内容主要介绍如何在 Ubuntu 上安装 Redis5 一些碎碎念&#xff1a; 本来这期内容介绍如何在 Centos 安装 Redis …

区块链可投会议CCF C--CT-RSA 2025 截止10.15 附2024录用率

Conference&#xff1a;The Cryptographers Track at RSA Conference (CT-RSA) CCF level&#xff1a;CCF C Categories&#xff1a;network and information security Year&#xff1a;2025 Conference time&#xff1a;San Francisco, California, USA • April 28–May …