LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

Sqlserver OVER(PARTITION BY)的简单理解

freeflydom
2023年10月28日 15:22 本文热度 575

ROW_NUMBER() OVER(…)

  1. 虽然写法很复杂,但这确实只是一个普通函数(就像字符串转数字这样的函数),可以得出一个值

  2. 这个函数不会改变数据条数,它的作用是给每个数据记录增加一个字段,这个字段值就是函数得到的值

  3. 函数虽然不会改变查询结果条数,但会改变结果的顺序。会按照某个字段a(这个字段会重复)分组,函数的值就是在每个分组内部的排序值(1,2,3,4.。。)

  4. 比如:一群人在排队买东西。会自动以家庭为单位分成一段一段的“小组”,然后又在家庭内部按照年龄大小做了排序(比如年龄大人在前面,小孩跟在大人后面),这个函数值就是这个家庭内部排序值

  5. 按照上面的比喻,这个函数就是ROW_NUMBER() over (PARTITION BY 家庭编号 order by 年龄)

  6. 函数完整的样子:ROW_NUMBER() OVER(PARTITION BY… ORDER BY…)。为什么要很啰嗦的再加一个ROW_NUMBER()? 因为前面这个ROW_NUMBER()会进一步控制函数的特性,后面会讲解【不过我个人认为这个前缀确实很啰嗦。让我设计的话,我会去掉它。因为对于大部分人可能就只会用最普通的函数使用方式,不写时就默认为ROW_NUMBER()多好】

类比一个完整的查询

select *, ROW_NUMBER() over (PARTITION BY 家庭编号 order by 年龄 desc) as “家庭地位” from 人员表
这句话除了得到了所有人员的信息之外,还额外得到了一个字段"家庭地位"(这里就默认:年龄越大,家庭地位越高)

理解了函数的含义和用法,然后我们就可以利用函数,比如,只获取所有家庭地位最高的人,那么就可以在我们再包一层,得到:
select * from( select *, ROW_NUMBER() over (PARTITION BY 家庭编号 order by 年龄 desc) as “家庭地位” from 人员表 ) t where t.家庭地位=1

引申

这样就可以解决类似:表T中 字段a会重复,但我们查询的结果又不想要重复的数据,并且要求只要其中最新的那一条
select * from( select *, ROW_NUMBER() over (PARTITION BY a order by create_time desc) as index from T ) t where t.index=1

或者topN问题:分组后,把每组前5个找出来
select * from( select *, ROW_NUMBER() over (PARTITION BY a order by create_time desc) as index from T ) t where t.index < 6

ROW_NUMBER()

这是一个控制 OVER函数特性的参数,而且不能省,over前面必须有一个。但并不是只有ROW_NUMBER()这一种。

假设在一共家庭中,有四个孩子,其中两个是双胞胎,年龄分别是5岁,7岁,7岁,9岁。
两个7岁的双胞胎 谁大谁小是很难说。理论上可以讲,两个孩子年龄是相同的。那么排队时,谁是老大谁是老二呢。
ROW_NUMBER():简单粗暴的做了自己的判断,哪条数据在前面,哪个就是老大(谁先生出来谁就是老大)。即便他们年龄一样(over函数值一样),它给这几个孩子定的家庭地位分别为4,3,2,1
DENSE_RENK():显得更公正一点:既然定好了按年龄排序,那么年龄相同,地位就是相同。它给四个孩子定的家庭地位分别为:3,2,2,1
RENK():比较特殊,它觉得那个5岁的孩子的家庭地位不应该是第3位。因为家里明明有4个孩子,它是最小的,两个并列第二之后,下一个应该是4(所以直接把3给跳过了)。所以它给的家庭地位分别是4,2,2,1

名称

下面这些都是这个函数的名称:
窗口函数分析函数分区函数,一般称为窗口函数(window function)。
一般关系型数据库都支持。由于属于比较高级的函数,都是在数据库不断完善的过程中增加的。比如mysql就是8.x之后才有。

和聚合函数对比

聚合函数:sum(), avg() 等统计函数 配合 group by 称为聚合函数
得出的是分组后 每一组等统计数据,改变了数据条数
如果想保持数据原有的样子,则需要使用窗口函数

窗口函数前面除了前面介绍的常用的三种,还可以使用sum() avg()等统计函数,变成:
sum() over(partition by ...) x
这里得到的x,就是对这个组内的求和,组内每一条数据都得到一个相同的值

进阶-和排序函数对比

虽然前面说窗口函数的核心是partition by,但实际上partition by也可以去掉。
也就是说:xxx() over(…) 这个函数非常灵活。
其中partition by也可去掉,但此时必须要有order by。
变成:xxx() over(order by …) xxx
此时窗口函数 的窗口就只有一个了:所有数据都在同一个窗口里。 只剩下排序功能,比如
dense_renk() over(over by 成绩) 名次
常见作用:给班级学生成绩排名,成绩一样的,名次就一样


————————————————

版权声明:本文为CSDN博主「发现存在」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/yunduanyou/article/details/122583303



该文章在 2023/10/28 15:25:45 编辑过
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved