每个组的SQL按另一列查找列顺序

时间:2017-05-27 23:40:55

标签: sql sql-server sql-server-2008 group-by aggregate

以下是数据:

studentid,state,score,date,modno,transactionno
1,IL,10,20170101,0,0
1,VA,20,20170102,1,1
1,FL,30,20170103,2,2
2,VA,40,20170101,0,0
2,IL,50,20170102,1,1
2,IN,60,20170103,2,2

以下是输出的方式:

studentid,state,score,date
1,IL,20,20170101
2,VA,60,20170102

所以基本上我们想按照studentid进行分组。

根据最低modno和transactionno找到第一个状态。

根据最高modno和transactionno找到第一个分数。

select studentid,
       (select top 1 state from student s1 where s.studentid = s1.studentid order by modno, transactionno) as state,
       (select top 1 score from student s1 where s.studentid = s1.studentid order by modno desc, transactionno desc) as score,
       (select top 1 date from student s1 where s.studentid = s1.studentid order by modno, transactionno) as date
from student s
group by studentid

以上是我在SQL 2008中的查询。还有其他方法可以编写此查询以获得更好的性能吗?在处理大型数据集时,它实际上显示出来,并且每组提取两个以上的列。

2 个答案:

答案 0 :(得分:0)

我想我会用条件聚合来解决这个问题:

select studentid,
       max(case when seqnum_asc = 1 then state end) as state,
       max(case when seqnum_desc = 1 then score end) as score,
       max(case when seqnum_asc = 1 then date end) as date
from (select s.*,
             row_number() over (partition by studentid order by modno, transactionno) as seqnum_asc,
             row_number() over (partition by studentid order by modno desc, transactionno desc) as seqnum_desc
      from student s
     ) s
group by studentid;

答案 1 :(得分:0)

猜猜你的输出是不正确的,或者我们在你的输出中没有理解日期部分。

尝试使用其他示例数据并告诉我们,

declare @t table(studentid int,states varchar(20), score int
,dates date,modno int,transactionno int)

insert into @t VALUES
(1,'IL',10,'20170101',0,0)
,(1,'VA',20,'20170102',1,1)
,(1,'FL',30,'20170103',2,2)
,(2,'VA',40,'20170101',0,0)
,(2,'IL',50,'20170102',1,1)
,(2,'IN',60,'20170103',2,2)
;with CTE as 
(
select studentid from @t
group by studentid  
)
SELECT t.studentid,ca.states,ca1.score,ca.dates 
from CTE t
cross apply(select top 1 t1.states,t1.dates from @t t1 
where t.studentid=t1.studentid 
order by modno,transactionno )ca
cross apply(select top 1 t1.score from @t t1 
where t.studentid=t1.studentid 
order by modno desc,transactionno desc )ca1
--cross apply(select top 1 t1.dates from @t t1 
--where t.studentid=t1.studentid 
--order by modno ,transactionno  )ca2