【问题标题】:SQL for each group find column order by another column每个组的 SQL 按另一列查找列顺序
【发布时间】:2017-10-28 14:01:46
【问题描述】:

这是数据:

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

所以基本上我们想按学生号分组。

根据最低的 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 中的查询。是否有其他方法可以编写此查询以获得更好的性能?当处理大型数据集并且每组提取超过两列时,它确实显示出来了。

【问题讨论】:

  • 为什么studentid 列在student 表中有多行?
  • 我不理解输出。应该使用什么日期?为什么 20 代表 id - 1?不应该是30吗?

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


【解决方案1】:

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

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;

【讨论】:

    【解决方案2】:

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

    试试这个其他示例数据并告诉我们,

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-30
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多