HiveSQL题——array_contains函数

目录

一、原创文章被引用次数

0 问题描述

1 数据准备

2 数据分析

​编辑

3 小结

二、学生退费人数

0 问题描述

1 数据准备

2 数据分析

3 小结

一、原创文章被引用次数

0 问题描述

   求原创文章被引用的次数,注意本题不能用关联的形式求解。

1 数据准备

   id表示文章id,oid表示引用的其他文章id,当oid为0时表示当前文章为原创文章。

create table if not exists  table18
(id    int comment '文章id',oid   int comment '引用的其他文章id'
) comment '文章信息表';insert overwrite table table18 values
(1,0),
(2,0),
(3,1),
(4,1),
(5,2),
(6,0),
(7,3);

2 数据分析

    题目要求的是原创文章被引用的次数,其中原创文章为oid等于0的文章,即求解文章id为【1,2,6】被引用的次数。常见的思路是用关联方式求解,具体SQL如下图所示:

思路一:用左连接 left join 


--思路一:用左连接 left join 
selectt1.id,count(t2.oid) as cnt
from (select * from table18 where oid = 0) t1left join(select * from table18 where oid <> 0) t2on t1.id = t2.oid
group by t1.id
order by t1.id;

 输出结果为:

 题意要求不能使用join等关联形式求解,其实该题本质是存在性计数问题

思路二:借助array_contains(array,element) 函数

selectnew_id,sum(flag)as cnt
from (selectid,oid,contains,-- 第二步:利用array_contains()函数判断引用的oid是否在原创文章id集合中,ture则记为1,false则记为0if(array_contains(contains, oid), 1, 0)    flag,-- 第三步:清洗数据,补充完整的原创文章if(array_contains(contains, oid), oid, if(oid = 0, id, null)) new_idfrom ( -- 第一步:构建原创文章id集合,作为辅助列selectid,oid,collect_set(if(oid = 0, id, null)) over () containsfrom table18) tmp1) tmp2
where new_id is not null
group by new_id;

    上述代码解析:通过array_contains(array,column) 函数进行存在性检测,如果array中包含column 则记为1,不存在记为0,关键公式: sum(if(array_contains(array,column),1,0))

上述代码解析:

第一步:构建原创文章id集合contains,将contains作为辅助列。

  selectid,oid,collect_set(if(oid = 0, id, null)) over () contains
from table18;

第二步:利用array_contains()函数,判断非原创的oid是否在原创文章id集合中,存在则计数为1,否则计数为0。

selectid,oid,contains,if(array_contains(contains, oid), 1, 0) as flag
from ( selectid,oid,collect_set(if(oid = 0, id, null)) over () containsfrom table18) tmp1;

第三步:清洗数据,对原创文章id补充完整

selectid,oid,contains,if(array_contains(contains, oid), 1, 0)   flag,--清洗数据,对原创文章id补充完整if(array_contains(contains, oid), oid, if(oid = 0, id, null)) new_id
from ( selectid,oid,collect_set(if(oid = 0, id, null)) over () containsfrom table18) tmp1;

 

   ps: 此处需要对原创文章id补充完整,否则会丢失记录。具体是:通过array_contains(contains,oid)去判断,代码为 if(array_contains(contains, oid), oid, if(oid = 0, id, null)) as  new_id   -->  代表的意思是如果oid存在于原创文章id构建的集合中,就取得该oid,如果不存在,再判断oid是否为0,如果是0,则取得id,否则记为null。

第四步:将new_id 为null的数据滤掉,并对new_id分组,求出各原创文章被引用的次数sum(flag)as cnt

selectnew_id,sum(flag)as cnt
from (selectid,oid,contains,-- 第二步:利用array_contains()函数判断引用的oid是否在原创文章id集合中,ture则记为1,false则记为0if(array_contains(contains, oid), 1, 0)    flag,-- 第三步:清洗数据,补充完整的原创文章idif(array_contains(contains, oid), oid, if(oid = 0, id, null)) new_idfrom ( -- 第一步:构建原创文章id集合,作为辅助列selectid,oid,collect_set(if(oid = 0, id, null)) over () containsfrom table18) tmp1) tmp2-- 第四步:将为null的数值过滤掉,并对new_id分组,求出各原创文章被引用的次数sum(flag)as cnt
where new_id is not null
group by new_id;

3 小结

 上述例子中利用array_contains(array,column)进行存在性检测,如果存在则记为1,不存在则记为0,核心计算公式为 sum(if(array_contains(array,value),1,0))

二、学生退费人数

0 问题描述

求截止当前月的学生退费总人数【当月的学生退费人数:上月存在,这月不存在的学生个数】。

1 数据准备

create table if not exists test19( dt string comment '日期',
stu_id string comment '学生id');insert overwrite table test19
values ('2020-01-02','1001'),('2020-01-02','1002'),('2020-02-02','1001'),('2020-02-02','1002'),('2020-02-02','1003'),('2020-02-02','1004'),('2020-03-02','1001'),('2020-03-02','1002'),('2020-04-02','1005'),('2020-05-02','1006');

2 数据分析

完整的代码如下:

select month,sum(month_cnt) over(order by month) as result
from(select month,lag(next_month_cnt,1,0) over(order by month) as month_cntfrom(select distinct t0.month as month,sum(if(!array_contains(t1.lead_stu_id_arr,t0.stu_id),1,0)) over(partition by t0.month) as next_month_cntfrom(select date_format(dt,'yyyy-MM') as month,stu_idfrom test19) t0left join(select month,lead(stu_id_arr,1) over(order by month) as lead_stu_id_arrfrom(select date_format(dt,'yyyy-MM') as month,collect_list(stu_id) as stu_id_arrfrom test19group by date_format(dt,'yyyy-MM') ) tmp1) t1on t0.month = t1.month) tmp2
) tmp3;

第一步:聚合每个月的stu_id,利用collect_list()函数(不去重)合并,具体sql如下:

select date_format(dt,'yyyy-MM') as month,collect_list(stu_id) as stu_id_arr
from test19
group by date_format(dt,'yyyy-MM') 

计算结果如下:

2020-01	[1001,1002]
2020-02	[1001,1002,1003,1004]
2020-03	[1001,1002]
2020-04	[1005]
2020-05	[1006]

第二步:按照月份排序,获取下一月合并之后的值,sql如下:

 select month,stu_id_arr,lead(stu_id_arr,1) over(order by month) as lead_stu_id_arr
from(selectdate_format(dt,'yyyy-MM') as month,collect_list(stu_id) as stu_id_arrfrom test19group by date_format(dt,'yyyy-MM')) tmp1;

计算结果如下:

2020-01	[1001,1002]	[1001,1002,1003,1004]
2020-02	[1001,1002,1003,1004]	[1001,1002]
2020-03	[1001,1002]	[1005]
2020-04	[1005]	[1006]
2020-05	[1006]	NULL

     ps:总体思路是利用数组差集函数求出差值集合后,再利用size()求出具体的个数,最后sum聚合即可。hive中的数组函数array_contains可以实现这个需求,该函数表示在数组中查询某个元素是否存在。在该题目中,借助此函数判断 当月某个学生id是否在下月(数据集合 -->数组)中存在,如果存在就为0,不存在标记为1。

 第三步:利用步骤2的结果与原表进行关联,获取当前学生id

selectt0.*,t1.*
from (selectdate_format(dt, 'yyyy-MM') as month,stu_idfrom test19) t0left join ( selectmonth,lead(stu_id_arr, 1) over (order by month) as lead_stu_id_arrfrom ( selectdate_format(dt, 'yyyy-MM') as month,collect_list(stu_id)       as stu_id_arrfrom test19group by date_format(dt, 'yyyy-MM')) tmp1) t1
on t0.month = t1.month;

结果如下:

2020-01	1001	2020-01	[1001,1002,1003,1004]
2020-01	1002	2020-01	[1001,1002,1003,1004]
2020-02	1001	2020-02	[1001,1002]
2020-02	1002	2020-02	[1001,1002]
2020-02	1003	2020-02	[1001,1002]
2020-02	1004	2020-02	[1001,1002]
2020-03	1001	2020-03	[1005]
2020-03	1002	2020-03	[1005]
2020-04	1005	2020-04	[1006]
2020-05	1006	2020-05	NULL

第四步:利用array_contains()函数判断当月的stu_id是否在下个月array数组中,如果存在标记0,不存在标记1。具体sql如下:

        select t0.month,t0.stu_id,if(!array_contains(t1.lead_stu_id_arr,t0.stu_id),1,0) as flagfrom(selectdate_format(dt,'yyyy-MM') as month,stu_idfrom test19) t0left join(select month,lead(stu_id_arr,1) over(order by month) as lead_stu_id_arrfrom(select date_format(dt,'yyyy-MM') as month,collect_list(stu_id) as stu_id_arrfrom test19group by date_format(dt,'yyyy-MM')) tmp1) t1on t0.month = t1.month

结果如下:

2020-01	1001	0
2020-01	1002	0
2020-02	1001	0
2020-02	1002	0
2020-02	1003	1
2020-02	1004	1
2020-03	1001	1
2020-03	1002	1
2020-04	1005	1
2020-05	1006	1

第五步:基于步骤四的结果,按照月份分组,对flag求和,得到下个月的学生退费人数

select  distinct t0.month,-- 求解下个月的退费人数sum(if(!array_contains(t1.lead_stu_id_arr,t0.stu_id),1,0)) over(partition by t0.month) as next_month_cnt
from  (selectdate_format(dt,'yyyy-MM') as month,stu_idfrom test19) t0
left join( select month,lead(stu_id_arr,1) over(order by month) as lead_stu_id_arrfrom( select date_format(dt,'yyyy-MM') as month,collect_list(stu_id) as stu_id_arrfrom test19group by date_format(dt,'yyyy-MM')) tmp1) t1
on t0.month = t1.month;

计算结果如下:

注意:第二列求是下个月的退费人数。

2020-01	0
2020-02	2
2020-03	2
2020-04	1

第六步:计算当前月的退费人数

    步骤五计算的是下一个月的学生退费人数,再利用 lag(next_month_cnt,1,0) over(order by month) 向上偏移一行,就得到当前月的退费人数

sql代码如下:

select month, --基于下月的退费人数month_cnt字段,向上偏移一行,就得到当前月的退费人数lag(next_month_cnt,1,0) over(order by month) as month_cntfrom(select distinct t0.month as month,sum(if(!array_contains(t1.lead_stu_id_arr,t0.stu_id),1,0)) over(partition by t0.month) as next_month_cntfrom(selectdate_format(dt,'yyyy-MM') as month,stu_idfrom test19) t0left join(select month,lead(stu_id_arr,1) over(order by month) as lead_stu_id_arrfrom(select date_format(dt,'yyyy-MM') as month,collect_list(stu_id) as stu_id_arrfrom test19group by date_format(dt,'yyyy-MM')) tmp1) t1on t0.month = t1.month) tmp2;

计算结果如下:

2020-01	0
2020-02	0
2020-03	2
2020-04	2
2020-05	1

计算截止到当前月的退费人数,sql代码如下:

select month,-- sum() over(order by ..) 窗口计算范围:上无边界(起始行)到当前行sum(month_cnt) over(order by month) as result
from(select month,lag(next_month_cnt,1,0) over(order by month) as month_cntfrom(select distinct t0.month as month,sum(if(!array_contains(t1.lead_stu_id_arr,t0.stu_id),1,0)) over(partition by t0.month) as next_month_cntfrom(selectdate_format(dt,'yyyy-MM') as month,stu_idfrom test19) t0left join(select month,lead(stu_id_arr,1) over(order by month) as lead_stu_id_arrfrom(select date_format(dt,'yyyy-MM') as month,collect_list(stu_id) as stu_id_arrfrom test19group by date_format(dt,'yyyy-MM')) tmp1) t1on t0.month = t1.month) tmp2
) tmp3;

计算结果为:

2020-01	0
2020-02	0
2020-03	2
2020-04	4
2020-05	5

3 小结

   针对存在性问题,一般的求解思路是:1.利用collect_set()或者 collect_list()函数进行聚合,将数据集转换成数据组。2.再利用array_contains()等函数判断集合(数组)中是否存在某元素,针对结果打上标签。3.再根据标签进行之后的分组聚合计算等。

ps:以上文章参考:

https://blog.csdn.net/godlovedaniel/article/details/119388498?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167921970316800184142859%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=167921970316800184142859&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-119388498-null-null.142^v74^control_1,201^v4^add_ask,239^v2^insert_chatgpt&utm_term=%E5%AD%98%E5%9C%A8%E6%80%A7%E9%97%AE%E9%A2%98&spm=1018.2226.3001.4187文章浏览阅读741次。本文对存在性问题进行了探讨和研究,此类问题往往需要对不同的记录做对比分析,我们可以先将符合条件的数据域按照collect_set()或collect_list()函数进行聚合转换成数组,然后获取历史的数据域放入当前行,最后利用hive中数组的相关处理手段进行对比分析。常用的hive数组处理函数如expode()、size()、array()、array_contains()等函数,本题就借助于hive ,array_contains()函数进行存在性问题分析。_sql 求截止当前月退费总人数https://blog.csdn.net/godlovedaniel/article/details/119388498?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167921970316800184142859%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=167921970316800184142859&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-119388498-null-null.142%5Ev74%5Econtrol_1,201%5Ev4%5Eadd_ask,239%5Ev2%5Einsert_chatgpt&utm_term=%E5%AD%98%E5%9C%A8%E6%80%A7%E9%97%AE%E9%A2%98&spm=1018.2226.3001.4187

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

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

相关文章

OpenCV 13 - 图像对比度和亮度的调节基本阈值操作

1 图像阈值 图像阈值是一种图像处理技术,用于将图像转换为二值图像。通过设定一个阈值,将图像中的像素值与阈值进行比较,将大于或小于阈值的像素分别设置为不同的像素值,从而实现图像的二值化处理。 2 阈值类型 2-1 阈值类型-阈值二值化(threshold binary) 2-2 阈值类型…

学习Android的第一天

目录 什么是 Android&#xff1f; Android 官网 Android 应用程序 Android 开发环境搭建 Android 平台架构 Android 应用程序组件 附件组件 Android 第一个程序 HelloWorld 什么是 Android&#xff1f; Android&#xff08;发音为[ˈnˌdrɔɪd]&#xff0c;非官方中文…

vue3 源码解析(6)— lifecycle 生命周期的实现

前言 对于 vue3 的生命周期&#xff0c;我们经常性会去疑问&#xff0c;生命周期有哪些呢&#xff0c;它是怎么去实现的&#xff0c; 又是什么时候调用的。 vue3 生命周期有哪些 下面这个表格列出了所有选项式api生命周期钩子和组合式api生命周期钩子&#xff0c;以及他们的…

GPT-4 Turbo 128k免费玩!字节跳动「Coze 扣子」AI Bot平台,零门槛打造你的专属聊天机器人,飞书、微信任你发布!

想要一个智能聊天助手&#xff0c;却苦于没有技术背景&#xff1f;别担心&#xff0c;字节跳动的“Coze扣子”AI Bot开发平台为你解忧&#xff01;无需编程知识&#xff0c;你也能快速搭建个性化的AI聊天机器人。 更厉害的是&#xff0c;“Coze扣子”不仅支持国内用户独享的云…

通过大疆PSDK,将第三方摄像头的视频流推到M300遥控器显示

1.首先确保跑通了大疆官方的demo&#xff0c;demo功能是可以将本地h264的视频文件推到遥控器显示。 2.将264格式设置为普通264&#xff08;默认为大疆264&#xff09;&#xff0c;更改demo里的代码如下 //returnCode DjiPayloadCamera_SetVideoStreamType(DJI_CAMERA_VIDEO_S…

《云原生安全攻防》-- 云原生安全概述

从本节课程开始&#xff0c;我们将正式踏上云原生安全的学习之旅。在深入探讨云原生安全的相关概念之前&#xff0c;让我们先对云原生有一个全面的认识。 什么是云原生呢? 云原生&#xff08;Cloud Native&#xff09;是一个组合词&#xff0c;我们把它拆分为云和原生两个词来…

Arduino 推出基于乐鑫 ESP32-S3 的 STEM 教育机器人

Arduino Alvik 是 Arduino Education 推出的一款新型机器人&#xff0c;可作为一种跨学科工具&#xff0c;为当前教育和未来机器人世界筑起连接的桥梁。Hackster 的 Gareth Halfacree 表示&#xff1a;“Alvik 的设计灵感来自 Arduino 简化复杂技术的理念&#xff0c;同时它也 …

【Spring Boot 3】事件机制

【Spring Boot 3】事件机制 背景介绍开发环境开发步骤及源码工程目录结构总结背景 软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花费或多或少的…

css实现按钮边框旋转

先上效果图 本质&#xff1a;一个矩形在两个矩形互相重叠遮盖形成的缝隙中旋转形成&#xff0c;注意css属性z-index层级关系 直接上代码 <div class"bg"><div class"button">按钮</div></div><style>.bg {width: 100%;heigh…

C++从零开始的打怪升级之路(day27)

这是关于一个普通双非本科大一学生的C的学习记录贴 在此前&#xff0c;我学了一点点C语言还有简单的数据结构&#xff0c;如果有小伙伴想和我一起学习的&#xff0c;可以私信我交流分享学习资料 那么开启正题 今天分享的是关于vector&#xff0c;这篇博客内容紧跟上一篇 1.…

80.如何评估一台服务器能承受的最大TCP连接数

文章目录 一、一个服务端进程最多能支持多少条 TCP 连接&#xff1f;二、一台服务器最大最多能支持多少条 TCP 连接&#xff1f;三、总结 一个服务端进程最大能支持多少条 TCP 连接&#xff1f; 一台服务器最大能支持多少条 TCP 连接&#xff1f; 很多朋友可能第一反应就是端…

【pytorch】anaconda使用及安装pytorch

https://zhuanlan.zhihu.com/p/348120084 https://blog.csdn.net/weixin_44110563/article/details/123324304 介绍 Conda创建环境相当于创建一个虚拟的空间将这些包都装在这个位置&#xff0c;不需要了可以直接打包放入垃圾箱&#xff0c;同时也可以针对不同程序的运行环境选…

有趣的css - 动态的毛玻璃背景

页面效果 此效果主要使用 backdrop-filter 属性&#xff0c;以及配合 animation 属性来实现毛玻璃模糊和一些动效。 此效果可适用于登录窗口&#xff0c;网站背景或者一些卡片列表中&#xff0c;使网页更具科技感和空间感。 核心代码部分&#xff0c;简要说明了写法思路&#x…

【Docker】使用VS创建、运行、打包、部署.net core 6.0 webapi

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Docker容器》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…

应用智能家居领域中的低功耗蓝牙模块

智能家居&#xff08;smart home, home automation&#xff09;是以住宅为平台&#xff0c;利用综合布线技术、网络通信技术、 安全防范技术、自动控制技术、音视频技术将家居生活有关的设施集成&#xff0c;构建高效的住宅设施与家庭日程事务的管理系统&#xff0c;提升家居安…

MySQL for update锁表还是锁行校验

select * from user where id 1 for update ; 1. for update作用 在MySQL中&#xff0c;使用for update子句可以对查询结果集进行行级锁定&#xff0c;以便在事务中对这些行进行更新或者防止其他事务对这些行进行修改。 当使用for update时&#xff0c;锁定行的方式取决于wh…

AI 智能体:探索自主智能的世界

AI 智能体&#xff1a;探索自主智能的世界 认真的飞速小软 飞速创软 2024-01-30 11:06 发表于新加坡 想象一下&#xff0c;在这样一个世界里&#xff0c;软件自身可以自主地与环境交互&#xff0c;根据收集的数据做出决策&#xff0c;并以最少的人工干预来执行任务。这些AI智能…

WPF 中 Loaded 和 Closing 窗口事件

在 WPF 中&#xff0c;Loaded 和 Closing 是两个常用的窗口事件。下面是对这两个事件的详细解释和示例说明&#xff1a; Loaded 事件&#xff1a; Loaded 事件在窗口&#xff08;或其他可视元素&#xff09;加载完成并准备好进行显示时触发。在 Loaded 事件中&#xff0c;您可…

2024美赛C题全网最早思路 网球运动(持续更新)

2024美赛已经于今天早上6点准时公布题目。本次美赛将全程跟大家一起战斗冲刺O奖&#xff01;思路持续更新。 2024 MCM Problem C: Momentum in Tennis &#xff08;网球运动的势头&#xff09; 注&#xff1a;在网球运动中&#xff0c;"势头"通常指的是比赛中因一系…

npm和yarn区别

都是包管理工具&#xff0c;但是yarn的出现是为了弥补npmV4&#xff08;npmV5结合yarn和自身的一些问题做了很大的升级&#xff0c;性能和速度都提高了&#xff09;及之前版本的一些问题 npmV4的缺点 npm install的时候巨慢。特别是新的项目拉下来要等半天&#xff0c;删除nod…