SqlServer分组排序取出每组顺序第一的数据

首先创建测试表并插入数据,

--创建测试表(汇率库表)
create table Exchangerate(
MoneyType varchar(100),--币种
Exchangerate varchar(100),--汇率
AddDate datetime--添加时间
);

--插入测试数据
insert into Exchangerate values ('美元','6.17','2018-09-11 12:30:53.283');
insert into Exchangerate values ('美元','6.36','2018-10-01 10:00:00.000');
insert into Exchangerate values ('英镑','8.74','2018-10-15 11:00:00.000');
insert into Exchangerate values ('英镑','8.53','2018-11-16 12:00:00.000');
insert into Exchangerate values ('港元','0.87','2018-08-01 11:00:00.000');
insert into Exchangerate values ('港元','0.79','2018-10-10 12:00:00.000');

汇率库表如下:
SqlServer分组排序取出每组顺序第一的数据_第1张图片
我想要得到数据为,每个币种下最新日期的汇率,效果图如下:
SqlServer分组排序取出每组顺序第一的数据_第2张图片
要实现这样的效果我有两条思路,一是按照币种分组后,取日期最大的所有数据。SQL如下:

SELECT * FROM Exchangerate SS1 
INNER JOIN (SELECT max(AddDate) AS AddDate, MoneyType FROM Exchangerate GROUP BY MoneyType) SS2 
on SS1.AddDate=SS2.AddDate and SS1.MoneyType=SS2.MoneyType

效果图如下:
SqlServer分组排序取出每组顺序第一的数据_第3张图片
虽然达到了想要的效果,但是在实际项目中,我觉得通过AddDate和MoneyType两列不一定能保证数据唯一性,我也不清楚这种写法有什么缺陷,但总感觉怪怪的,所以实际中我没有采用这种写法。下面是第二个思路:
按照币种分组,且按照日期降序排序,取出每组中的序号为1的所有数据。SQL如下:

select * from (
select *,row_number() over(partition by MoneyType order by AddDate desc) rn from Exchangerate
) tn where tn.rn=1;

效果图如下:
SqlServer分组排序取出每组顺序第一的数据_第4张图片
SQL中用到了over()函数,这是开窗函数,与聚合函数一样,开窗函数也是对行集组进行聚合计算,但是它不像普通聚合函数那样每组只返回一个值,开窗函数可以为每组返回多个值,因为开窗函数所执行聚合计算的行集组是窗口。在 ISO SQL 规定了这样的函数为开窗函数,在 Oracle 中则被称为分析函数。

over()函数很重要,在SqlServer中的分页方法有很多,其中top not in方式是最常用的,而使用ROW_NUMBER() over()函数是最好的解决分页的方法,举例如下:

-- 汇率库表.分页查询,查询第6页的数据,每页2条
select * from (
select *,row_number() over(order by AddDate) as rowid from Exchangerate
)as b
where rowid between (6-1)*2+1 and 6*2

在解决问题中,从网上参考了很多资料,参考链接如下:
https://blog.csdn.net/wulex/article/details/79288561
https://www.jb51.net/article/141174.htm

你可能感兴趣的:(SqlServer数据库)