SQL | 窗口函数 row number + partition by 排序

SQL | 窗口函数 row number + partition by 排序目录1  背景2  SQL牛逼函数走起来2.1  Step12.2  SQL实现12.3  Step22.4  SQL实现22.5  补充-collect函数2.5.1  SQL语句3  头条面试SQL题3.1&nbs…

大家好,又见面了,我是你们的朋友全栈君。

1 背景

今天实习学到了一个很牛逼的sql函数,而且解决了一个之前面试头条时候的SQL问题!(也知道了为啥头条挂了…毕竟当时SQL做错了)

  • 前一篇关于SQL的推文(给链接)最后形成的表是这样的:
import pandas as pd
df = pd.read_excel('./sql数据处理与提取-窗口函数-0327.xlsx', sheet_name='interest0')
df
deviceid categoryinterest interests1 interests_news interests_score
0 65762973 军事:1.0,娱乐:0.917,军事/装备:0.916,娱乐/明星八卦:0.874,历史/古… 体育/冰雪运动:0.641 体育/冰雪运动 0.641
1 774830731 历史/古代史:1.0,历史:0.5 历史/古代史:1.0 历史/古代史 1.000
2 65762973 军事:1.0,娱乐:0.917,军事/装备:0.916,娱乐/明星八卦:0.874,历史/古… 人文/人文科普:0.584 人文/人文科普 0.584
3 124901984 情感/两性:1.0,历史/古代史:0.933,娱乐:0.901,情感:0.742,体育/乒乓… 体育/NBA:0.566 体育/NBA 0.566
4 874657455 体育/国际足球:9.063,体育/中国足球:3.019,娱乐/综艺:1.947,体育/NBA… 体育/乒乓球:0.207 体育/乒乓球 0.207

现在的需求是这样:

  • 计算每一个deviceid下interests_score前三以及对应的interests_news
  • 并且interests_news的前面的标签不能有“娱乐” “要闻” “社会”
  • 根据第二步拆开之后,如果后面为空,即没有联合标签,取前面的,非空则取后面的。

2 SQL牛逼函数走起来

2.1 Step1

  • Step1:使用pslit函数根据反斜杠将interests_news进行切分为tag_1和tag_2

2.2 SQL实现1

(select
		deviceid,interests_news,split(interests_news,'/')[0] as tag_1,split(interests_news,'/')[1] as tag_2, 
		interests_score
		from
		(select
			deviceid,categoryinterest,interests1,
			split(interests1, ':')[0] as interests_news,
			split(interests1, ':')[1] as interests_score
		from
			(select
			deviceid,categoryinterest,interests1
			from
			table1
			lateral view explode(split(categoryinterest,',')) tb1 as interests1
			where
			day=20190313
			group by
			deviceid,categoryinterest,interests1
			)t1
		)t2
		where
		interests_score>=0.5 and interests_score<=1 --获取高分值兴趣点
		group by
		deviceid,interests_news,split(interests_news,'/')[0] ,split(interests_news,'/')[1],interests_score
		-- 疑问 为啥没有直接用tag_1 tag_2 
	)interests0

2.3 Step2

Step2:均在select中实现!+ where限制

  • 并且舍弃tag_1为“娱乐” “要闻” “社会”三类的 where判断
  • 合并tag_1与tag_2 使用case when 如果tag_2非空则取tag_2 否则取tag_1
  • 使用row number函数 + partition by + order by 并且取排名前三 where

3.4 SQL实现2

select
	deviceid,
	interests_score,
	tag_type
--	collect_set(tag_type)as interests_array --行转纵
from
	(select 	
	deviceid,interests_news,interests_score,
	case when tag_2 is not null then tag_2 when tag_2 is null then tag_1 end as tag_type,--二级标签不为空取二级标签值,若二级为空,则取一级标签
	row_number() over(partition by deviceid order by interests_score desc) rank --对单个用户,按照分值降序
	-- 表示根据deviceid分组,在分组内部根据 interests_score 降序,而此函数计算的值就表示每个id内部根据score排序后的顺序编号记为rank(组内连续的唯一的)
	
	from
	(select
		deviceid,interests_news,split(interests_news,'/')[0] as tag_1,split(interests_news,'/')[1] as tag_2, 
		interests_score
		from
		(select
			deviceid,categoryinterest,interests1,
			split(interests1, ':')[0] as interests_news,
			split(interests1, ':')[1] as interests_score
		from
			(select
			deviceid,categoryinterest,interests1
			from
			portal.ddm_user_multiprod_user_portrait_d
			lateral view explode(split(categoryinterest,',')) tb1 as interests1
			where
			day=20190313
			group by
			deviceid,categoryinterest,interests1
			)t1
		)t2
		where
		interests_score>=0.5 and interests_score<=1 --获取高分值兴趣点
		group by
		deviceid,interests_news,split(interests_news,'/')[0] ,split(interests_news,'/')[1],interests_score
		-- 疑问 为啥没有直接用tag_1 tag_2 
	)interests0
	where
	tag_1 not in ('娱乐','社会','要闻','未知') --去除主流兴趣标签影响
	)interests00
	where
	rank<=4 --获取几类二级标签的组合 取top4
group by
	deviceid,
	interests_score,
	tag_type
  • 结果为:
df = pd.read_excel('./sql数据处理与提取-窗口函数-0327.xlsx', sheet_name='step3')
df
deviceid interests_news tag_type interests_score rank
0 65762973 体育/冰雪运动 冰雪运动 0.641 1
1 65762973 人文/人文科普 人文科普 0.584 2
2 774830731 历史/古代史 古代史 1.000 1
3 124901984 体育/NBA NBA 0.566 1
4 874657455 体育/乒乓球 乒乓球 0.207 1

总结:

  • row number()函数特别好用 往往配合 partition by 以及 order by
    参考:https://www.cnblogs.com/icebutterfly/archive/2009/08/05/1539657.html

  • 上述函数适用情况:当需要根据某一个标签进行分组并且在组内需要根据另一个字段进行降序or升序排列 打上排名 视情况取前几名 【下面还会举一个头条面试的例子】

  • case when函数语句:使用在select语句中,并且是

    case when *** then *** when *** then *** (else *** ) end as 新字段名称

2.5 补充-collect函数

作用:用来多行转为一行的方法 它返回一个消除了重复元素的对象集合, 其返回值类型是 array 。

SQL语句:

select deviceid, collect_set(tag_type) as interests_array 
from 上述表
  • 结果为:
deviceid interests_array
0 65762973 [“冰雪运动”, “人文科普”]
1 774830731 [“古代史”]
2 124901984 [“NBA”]
3 874657455 [“乒乓球”]

3 头条面试SQL题

3.1 题目

前段时间找实习去头条面试,最后被虐的体无完肤…其中面试官灵魂拷问:你SQL咋样?如果1-10分,你给自己的SQL打几分?我当时内心就无语了!?还有这种操作?嗨呀,SQL当时完全自学,当时没有实习,没有任何场景应用,所以水平明显很次,内心TMD脸上笑嘻嘻的说:6分,及格吧。面试官同样皮笑肉不笑的说,好,那我出个题哈,(面试官内心os:小样,那我就出个6分水平的题,看你答不答得出来!)

题目是这样的:
现在有一张表,有三列,一列是学生的姓名,一列是学生的雅思考试成绩,一列是考试时间,学生可以多次参加雅思考试,现在想要统计出不同学生最近一次考试时间的成绩!你说说思路吧!

3.2 实现

嗨呀,当时稍微想了一下,感觉不难嘛,于是脱口而出:

select name, score, max(time) from table group by name 

当时信心满满,但是回来和同学一聊,有说对的有说错的,尴尬!直到今天在公司遇到一个和这个很类似的问题啊!于是请教了我的leader,并且当场给我建了个临时表show了一把,结果是我错了,这种方法是不对的!

正确答案现在来看,肯定不难了:

  • 首先取出三列,然后使用row number函数 根据姓名进行partition by 然后对时间进行降序排列 取rank小于等于1的即可
select *, 
Row_Number() over (partition by name order by time desc) rank 
from IELTS
where rank <= 1

那当时的做法对不对呢?废话不多话,建一个表试试!

3.2 建表

在这里插入图片描述

结果为:

在这里插入图片描述
注:这次的代码刚在本机竟然没有跑通,后天去公司再请教下leader…不过逻辑肯定是没问题的~

未完待续


0716更新:后续请参考博客:SQL | 关于窗口函数的补充

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/139467.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • NLP学习之使用pytorch搭建textCNN模型进行中文文本分类

    NLP学习之使用pytorch搭建textCNN模型进行中文文本分类最近花周末两天时间利用pytorch实现了TextCNN进行了中文文本分类,在此进行记录。数据获取中文数据是从https://github.com/brightmart/nlp_chinese_corpus下载的。具体是第3个,百科问答Json版,因为感觉大小适中,适合用来学习。下载下来得到两个文件:baike_qa_train.json和baike_qa_valid.json。内容如下:{…

    2022年6月28日
  • osip和mysql_osip2/eXosip2调试笔记

    osip和mysql_osip2/eXosip2调试笔记软件版本:libosip2-3.3.0.tar.gzlibeXosip2-3.3.0.tar.gz./configure–prefix=/opt/sip/target–disable-staticmakemakeinstall测试代码:代码来源:http://blog.csdn.net/bat603/archive/2006/11/15/1386277.aspx1、UAS…

    2022年6月24日
  • 重启MySQL服务(怎么重启mysql服务)

    重启MySQL服务(怎么重启mysql服务)一、MYSQL服务我的电脑——(右键)管理——服务与应用程序——服务——MYSQL——开启(停止、重启动)二、命令行方式Windows1.点击“开始”->“运行”(快捷键Win+R)。2.启动:输入netstopmysql3.停止:输入netstartmysql提示*RedhatLinux也支持servicecommand,启动:#servicemysqldstar…

    2022年4月18日
  • 安装keil5时,注册机在解压后消失的解决以及使用注册机破解keil5时,无法破解

    安装keil5时,注册机在解压后消失的解决以及使用注册机破解keil5时,无法破解这里写自定义功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML图表FLowchart流程图导出与导入导出导入全新的界面设计,将会带来全新的写作体验;在创作中心设置你喜爱的代码高亮样式,Markdown将代码片显示选择的高亮样式进行展示;增加了图片拖拽功能,你可以

    2022年6月2日
  • matlab归一化方法,数据归一化的基本方法

    matlab归一化方法,数据归一化的基本方法1.线性归一化简单公式表达:y=(x-minValue)/(maxValue-minValue)其中,x是归一化之前的数据,y是归一化之后的数据,maxValue和minValue分别对应这一组数据中的最大值和最小值。范围:[0,1]。适用于:把原来数据等比例缩放限定在某一范围内,在不涉及距离度量和协方差计算的时候使用。2.标准差归一化简单公式表达:y=(x-μ)/σ其中,…

    2022年6月23日
  • 100TB大数据存储方案

    100TB大数据存储方案HiveHbase存储介质:https://www.zhihu.com/question/46392643?sort=created请问,在家里攒一套100TB-200TB的存储有什么架构方案可以借鉴的?预算10万以内,性价比越高越好 带宽和吞吐量不是很重要,USB3.0/千兆LAN单出口都可以接受,软raid硬raid都行 可以是机柜形式,有单间机房 耗电无所谓…

    2022年10月6日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号