窗口函数row_number() over (partition by 字段1 order by 字段2)

文章介绍了数据库中的窗口函数,如row_number(),用于解决特定问题,如按保单号分组并排序。文章提供了一个去除重复记录的例子,并展示了如何查询每个学生成绩最高的一次记录,通过两种方法:开窗函数和groupby。作者强调了学习新知识时的思考和实践重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库中的窗口函数

1.介绍

SQL Server、MySQL还是Oracle都有窗口函数。今天前辈教我这个东西,还是第一次见识这个函数,还是有收获的。

2.开窗函数的语法

窗口函数的语法:over (partition by 字段1 order by 字段2),括号中的两个关键词partition byorder by 可以只出现一个。over() 前面是一个函数,如果是聚合函数,那么order by 不能一起使用。

3. 排名开窗函数row_number() over (partition by 字段1 order by 字段2)

今天在工作中遇到一个问题,由于一个保单号(主键)下面有多个产品,每个产品下能操作的保全项也不一样。导致列表显示一个保单号前面所有字段数值都一样,就是最后一个字段不一样。
在这里插入图片描述
例如图中标记的两套记录,我想剔除下面的一条。

select a.grpcontno,
	   a.appntno,
	   a.grpname,
	   a.state,
	   a.peoples,
	   ....
	   a.edortype
from (select b.grpcontno,
			 b.appntno,
			 b.grpname,
			 b.state,
			 b.peoples,
			 ......
			 b.edortype,
			 row_number() over (partition by grpcontno order by len desc) as t 
	 from (select distinct a.grpcontno,
	 					   a.appntno,
	 					   a.state,
	 					   (select count(1) 
	 					   		from lcinsured lc 
	 					   	where lc.grpcontno = a.grpcontno
	 					   		and lc.insuredstat = '11') peoples,
	 					   )
	 					   ......
	 					   (select to_char(wm_concat(lm.edorcode))
	 					   		from lmriskedoritem lm
	 					   	where lm.edorcode in 
	 					   		  ('NI', 'ZT', 'IR', 'PB', 'IC')
	 					   and lm.riskcode = lm.riskcod) edortype,
	 					   (select length(to_char(wm_concat(lm.edorcode))
	 					   		from lmriskedoritem lm
	 					   	where lm.edorcode in 
	 					   		  ('NI', 'ZT', 'IR', 'PB', 'IC')
	 					   and lm.riskcode = lm.riskcod)) len
	 	from lcgrpcont     a,
	 		 ldpbalanceon  b,
	 		 lccontgetpol  c,
	 		 lcproposal    d,
	 		 lcagenttocont x
	 	left join lcpol lc
	 	  on x.policyno = lc.grpcontno
	 	where a.grpcontno = b.grpcontno
	 	and a.prtno = d.grppropno
	 	and d.contplantype = '00'
	 	and a.grpcontno = c.contno
	 	and x.policyno = a.grpcontno
	 	and c.receivepoldate is not null
	 	and lc.riskcode <> '8904'
	 	and a.state = '11'
	 	order by c.cvalidate desc) b ) a
where a.t = 1

这样的话就能剔除掉上面所说的那条数据。
该例子中,子查询有点多,看的眼花。。。。

学习最重要的就是会举一反三,下面列举一个简单的例子。
查询每个学生成绩最高的一次记录。
在这里插入图片描述

-- 方法一: 开窗函数
SELECT
	b.sid,
	b.name,
	b.gender,
	b.age,
	b.score 
FROM
	(
	SELECT
		a.sid,
		a.name,
		a.gender,
		a.age,
		a.score,
		ROW_NUMBER() over ( PARTITION BY a.sid ORDER BY a.score DESC ) AS t 
	FROM
		(
		SELECT
			t1.sid,
			t1.NAME,
			( SELECT ld.codename FROM ldcode ld WHERE ld.codetype = 'gender' AND ld.`code` = t1.gender ) gender,
			t1.age,
			t2.score 
		FROM
			stu_info t1
			LEFT JOIN c_course t2 ON t1.sid = t2.sid 
		-- ORDER BY t2.score DESC 
		) a 
	) b 
WHERE
	b.t = 1 ;

-- 方法二: group by 
SELECT
		t1.sid,
		t1.name,
		( SELECT ld.codename FROM ldcode ld WHERE ld.codetype = 'gender' AND ld.`code` = t1.gender ) gender,
		t1.age age,
		MAX( t2.score) score 
	FROM
		stu_info t1
		LEFT JOIN c_course t2 ON t1.sid = t2.sid 
	GROUP BY
		t1.sid, t1.age
		ORDER BY MAX( t2.score) 

4.总结

遇到困难,首先自己要先去思考,自己动手实践。实在是搞不定就请教大佬,不要不敢问,脸皮厚一点。没人会觉得你差,学会积累。拜拜啦,洗澡睡觉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只想躺平(已上岸)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值