(sql server)sql 分组取top1

  经常遇到这样的问题,相同ID的数据有多笔,但是只能任取其中一笔,下面是我的一个思考过程和学习过程。虽然比较基础和简单,但是总会有人不知道,也可以学习一下。

1:建表和初始化数据

create table TestTop
(
ID nvarchar(10), 
Name nvarchar(10),
Name_en nvarchar(10),
NoOne char(5),
NoTwo char(5),
NoThree char(5)
)
insert into TestTop values('I00001',N'测试1','abc','00001','00002','00003')
insert into TestTop values('I00001',N'测试1','abc','00001','00002','00003')
insert into TestTop values('I00001',N'测试2','bca','00002','00002','00003')
insert into TestTop values('I00001',N'测试3','aaa','00003','00001','00003')

insert into TestTop values('I00002',N'2测试1','gfg','00001','05002','09003')
insert into TestTop values('I00002',N'2测试2','dd','0022','00002','00003')

2:首先想到的肯定是group by ,但是group by 后面的栏位必须是聚合函数,如果用max或min,每个栏位取都不一定是同一笔数据的信息,这样就有错误

select * from TestTop
select ID,max(Name)Name,max(Name_en)Name_en,max(NoOne)NoOne,max(NoTwo)NoTwo,max(NoThree)NoThree
from TestTop group by ID

3:本着先思考再找答案的思想,我想了一下,想到了一个很笨的办法,如果我每个ID都排序取top1,那么top1的数据是固定的,这样可以取到完整的一条,这样是可以实现的。

但是还是有一个问题,如果有2条数据一模一样,那这样还要distinct一下。这个方法有个bug,如果有栏位为null,等于的时候就会出问题。

select * from TestTop
select distinct ID,Name,Name_en,NoOne,NoTwo,NoThree from TestTop TT
where TT.Name=(select top 1 Name from TestTop where ID=TT.ID order by ID,Name,Name_en,NoOne,NoTwo,NoThree asc)
and TT.Name_en=(select top 1 Name_en from TestTop where ID=TT.ID order by ID,Name,Name_en,NoOne,NoTwo,NoThree asc)
and TT.NoOne=(select top 1 NoOne from TestTop where ID=TT.ID order by ID,Name,Name_en,NoOne,NoTwo,NoThree asc)
and TT.NoTwo=(select top 1 NoTwo from TestTop where ID=TT.ID order by ID,Name,Name_en,NoOne,NoTwo,NoThree asc)
and TT.NoThree=(select top 1 NoThree from TestTop where ID=TT.ID order by ID,Name,Name_en,NoOne,NoTwo,NoThree asc)

4:刚那个方法虽然可以实现,但是如果栏位很多,那要写的where条件就太多了,这时我就在网上查询了一下,发现了一个好用的办法。

row_number 方法配合partition by 分组编号,再取编号为1的就可以实现了。

partition可以分区,为每个ID编号,ID切换后重新开始编号,这个方法以前还没见过,算是学习了。

select * from TestTop
select ROW_NUMBER() over(partition by ID order by ID) pid, * into #temp from TestTop
select * from #temp
select ID,Name,Name_en,NoOne,NoTwo,NoThree from #temp where pid=1
drop table #temp

 其实就些就是认识了partition分区...

 

posted @ 2014-04-24 17:38  清风君  阅读(8569)  评论(0编辑  收藏  举报