SQL专项练习第二天

news2024/11/28 4:36:28

        在数据处理和分析中,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 都能提供高效的解决方案。

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

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

相关文章

随时随地,轻松翻译:英汉互译软件的便捷之旅

翻译英汉互译工具&#xff0c;就如同一位随时待命的语言助手&#xff0c;在这纷繁复杂的语言世界中为我们搭建起理解与沟通的桥梁。接下来&#xff0c;让我们一同深入了解这些神奇的英汉互译工具&#xff0c;探索它的诸多功能和独特魅力。 1.福晰在线翻译 链接直达>>h…

柔性数组 初学版

1.定义 结构中的最后⼀个元素允许是未知⼤⼩的数组&#xff0c;这就叫做『柔性数组』成员 有些编译器会报错⽆法编译可以改成&#xff1a; typedef struct st_type { int i; int a[]; // 柔性数组成员 }type_a; 2.柔性数组的特点&#xff1a; • 结构中的柔性数组成员前…

毕业设计_基于springboot+layui+mybatisPlus的中小型仓库物流管理系统源码+SQL+教程+可运行】41004

毕业设计_基于springbootlayuimybatisPlus的中小型仓库物流管理系统源码SQL教程可运行】41004 下载地址&#xff1a; https://download.csdn.net/download/qq_24428851/89843203 技术栈 后端&#xff1a;springboot、mybatis-plus、shiro 前端&#xff1a;layUI 存储&…

德国法院允许非营利组织LAION抓取受版权保护的图像用于AI训练

在人工智能快速发展的今天&#xff0c;一场发生在德国汉堡的法庭裁决为AI训练数据的收集和使用带来了新的讨论。这起案件不仅引发了公众对AI与版权之间关系的深思&#xff0c;也为未来AI发展的法律框架提供了重要参考。 事件的起因是非营利组织LAION在未经授权的情况下&#x…

SpringBoot日志打印实践

背景 在项目当中&#xff0c;我们经常需要打印一些日志埋点信息&#xff0c;这些日志埋点信息&#xff0c;在后续软件的运维、稳定性建设中发挥了巨大的作用&#xff1a; 问题追踪&#xff1a;通过埋点日志中的关键信息&#xff0c;帮助定位系统异常原因系统监控&#xff1a;…

《Linux从小白到高手》理论篇:Linux用户和组相关的命令

List item 本篇介绍Linux用户和组相关的命令&#xff0c;看完本文&#xff0c;有关Linux用户和组相关的常用命令你就掌握了99%了。Linux用户和组相关的命令可以分为以下六类&#xff1a; 一.用户和用户组相关查询操作命令&#xff1a; Id id命令用于显示用户的身份标识。常见…

解表之紫苏

** 声明&#xff1a;本文介绍的中药仅供学习使用&#xff0c;请勿擅自使用&#xff0c;否则后果自负&#xff01;&#xff01;&#xff01;因水平有限&#xff0c;如有不当之处&#xff0c;请批评指正&#xff01;&#xff01;&#xff01;&#xff01;图片来源网络&#xff0…

No.1 | 从小白到入门:我的渗透测试笔记

嘿&#xff0c;小伙伴们&#xff01;好久不见啊&#xff0c;是不是都以为我失踪了&#xff1f;&#x1f602; 其实呢&#xff0c;最近一直在埋头苦学&#xff0c;感觉自己就像是在技术的海洋里游泳&#xff0c;每天都在吸收新知识。现在终于有时间冒个泡&#xff0c;跟大家分享…

Linux进程控制(2)(进程程序替换1)

目录 续--上一章 1.WIFEXITED && WEXITSTATUS 2.非阻塞等待 进程程序替换 1.先观代码 && 现象 2.原理解释 3.将代码改成多进程版 4.使用所有的替换方法&#xff0c;并且认识函数参数的含义 续--上一章 1.WIFEXITED && WEXITSTATUS 若需要知道退…

ODX相关基础知识普及

一、ODX概述 1.1 背景与意义 介绍汽车电子化的发展 随着科技的飞速发展&#xff0c;汽车电子化已成为现代汽车工业的重要趋势。从早期的机械控制到现代的电子控制&#xff0c;汽车电子化经历了巨大的变革。早期&#xff0c;汽车的主要控制系统都是基于机械原理&#xff0c;通…

Cisco ACI Simulator 6.0(7e)M 发布下载,新增功能简介

Cisco ACI Simulator 6.0(7e)M - ACI 模拟器 Application Centric Infrastructure (ACI) Simulator Software 请访问原文链接&#xff1a;https://sysin.org/blog/cisco-acisim-6/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.…

[C/C++开发]链接动态库在不同操作系统上的行为

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 想必很多人已经了解了动态库与静态库,在实际开发中也经常使用. 但是,有必要了解在windows和Linux上开发c程序生成和链接动态库的不同行为,因为经常混淆或者自以为找到了动态库,这里简单学习并澄清一下.其中许多内容来…

【Python】pyenv:管理多版本 Python 环境的利器

pyenv 是一个强大的 Python 版本管理工具&#xff0c;它允许开发者在同一台计算机上轻松安装和管理多个 Python 版本。对于需要在不同项目中使用不同 Python 版本的开发者来说&#xff0c;pyenv 是一个非常有用的工具&#xff0c;因为它可以帮助用户在全局和项目级别控制 Pytho…

PCL 给点云添加高斯噪声并保存

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 添加高斯噪声实现 2.1.2 可视化函数 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#xff08;长期更新&…

角色动画——RootMotion全解

1. Unity(2022)的应用 由Animtor组件控制 在Animation Clip下可进行详细设置 ​ 官方文档的介绍(Animation选项卡 - Unity 手册) 上述动画类型在Rag选项卡中设置: Rig 选项卡上的设置定义了 Unity 如何将变形体映射到导入模型中的网格&#xff0c;以便能够将其动画化。 对于人…

污水排放口细粒度检测数据集,污-水排放口的类型包括10类目标,10000余张图像,yolo格式目标检测,9GB数据量。

污水排放口细粒度检测数据集&#xff0c;污-水排放口的类型包括10类目标&#xff08;1 合流下水道&#xff0c;2 雨水&#xff0c;3 工业废水&#xff0c;4 农业排水&#xff0c;5 牲畜养殖&#xff0c;6 水产养殖&#xff0c;7 地表径流&#xff0c;8 废水处理厂&…

yub‘s Algorithmic Adventures_Day5

Day5 反转链表 link&#xff1a;206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 思路分析 与数组不同&#xff0c;链表没必要定义新的链表进行存储【对内存空间的浪费】 直接改变next指针即可. 注意头节点指向的下一个节点为null 双指针法 class Solution {publi…

杂谈c语言——6.浮点数的存储

1.浮点数在内存中的存储 常⻅的浮点数&#xff1a;3.14159、1E10等&#xff0c;浮点数家族包括&#xff1a; float、double、long double 类型。 浮点数表⽰的范围&#xff1a; float.h 中定义 1.1 练习 #include<stdio.h>int main() {int n 9;float* pFloat (floa…

Golang | Leetcode Golang题解之第456题132模式

题目&#xff1a; 题解&#xff1a; func find132pattern(nums []int) bool {candidateI, candidateJ : []int{-nums[0]}, []int{-nums[0]}for _, v : range nums[1:] {idxI : sort.SearchInts(candidateI, 1-v)idxJ : sort.SearchInts(candidateJ, -v)if idxI < idxJ {ret…

智能视界·大模型驱动视频矩阵管理系统

开头先配两张ER图 一张不带字段&#xff0c;一张带字段&#xff0c;剩下的内容按需拿取 1.产品介绍 产品名称&#xff1a; 智能视界大模型驱动视频矩阵管理系统 主要功能&#xff1a; 智能视频分析与识别 功能介绍&#xff1a;该系统集成先进的人工智能大模型&#xff0c;能…