如何在SQL中获取每组的First和Last记录?

时间:2015-06-30 01:40:01

标签: sql sql-server sql-server-2008

正如标题所示,我想选择以GROUP BY

分组的每组行的第一行和最后一行

我在这张表中包含以下数据

id  group   val   start   end
1   10      36    465     89        
2   10      35    55      11        
3   10      34    20      456       
4   20      38   1140     1177      
5   20      22    566     788       
6   20      1235  789     4796      
7   20      7894  741     1067   

我需要获取列开始的第一个值以及列的最后一个值以组列的方式结束

结果表应如下所示

   id  group   val   start   end
    1   10      36    465     89
    3   10      34    20      456       
    4   20      38   1140     1177
    7   20      7894  741     1067  

我做了一个查询,但是First_valueLAST_VALUE以及over (partition by)它在sql server 2012中有效,但在sql server 2008中无效,我需要查询可以在sql server 2008

中执行

谢谢

5 个答案:

答案 0 :(得分:8)

如何使用ROW_NUMBER

SQL Fiddle

WITH Cte AS(
    SELECT *,
        RnAsc = ROW_NUMBER() OVER(PARTITION BY [group] ORDER BY val),
        RnDesc = ROW_NUMBER() OVER(PARTITION BY [group] ORDER BY val DESC)
    FROM tbl
)
SELECT
    id, [group], val, start, [end]
FROM Cte
WHERE
    RnAsc = 1 OR RnDesc = 1
ORDER BY [group], val

答案 1 :(得分:4)

这是一种方式 -

select  t.*
from    tbl t
join    (
        select [group],
               min(val) as val_1,
               max(val) as val_2
        from   tbl
        group by [group]
        ) v
     on t.[group] = v.[group]
    and (t.val = v.val_1
     or t.val = v.val_2);

小提琴:http://sqlfiddle.com/#!3/c682f/1/0

另一种方法:

select id, [group], val, [start], [end]
from(
select t.*,
       max(val) over(partition by [group]) as max_grp,
       min(val) over(partition by [group]) as min_grp
from tbl t
) x
where val in (max_grp,min_grp)

答案 2 :(得分:0)

select tt.id, tt.groups, tt.val, x.sstart, tt.[end] from test_table tt join
(Select groups,First_value(start) over (partition by groups order by groups) sstart from test_table  
Union
Select groups,Last_Value(start) over (partition by groups order by groups) sstart from test_table) as x
on tt.start=x.sstart
Order by tt.groups, sstart Desc

答案 3 :(得分:0)

如何两次查询“ UNION”

SELECT TOP 1 EmployeeId, AttendenceId, Intime
FROM EmployeeAttendence
WHERE AttendenceDate >='1/18/2020 00:00:00' 
  AND AttendenceDate <='1/18/2020 23:59:59'
GROUP BY EmployeeId,AttendenceId,Intime
ORDER BY AttendenceId  

SELECT TOP 1 EmployeeId, AttendenceId, OutTime
FROM EmployeeAttendence
WHERE AttendenceDate >='1/18/2020 00:00:00' 
  AND AttendenceDate <='1/18/2020 23:59:59'
GROUP BY EmployeeId, AttendenceId, OutTime
ORDER BY AttendenceId desc 

答案 4 :(得分:0)

这是一个银行帐户示例:

create table transactions (
id integer identity(1,1),
aDateTime datetime not null default getdate(),
OnHand float,
AmountWithDrawn float,
AmountDeposited float,
NewOnhand float
)

insert into transactions (aDateTime, OnHand, AmountWithDrawn, AmountDeposited, NewOnhand) values ('01-jan-2021 08:15', 0, 0, 1000, 1000);

insert into transactions (aDateTime, OnHand, AmountWithDrawn, AmountDeposited, NewOnhand) values ('05-jan-2021 08:15', 1000, 100, 0, 900);

insert into transactions (aDateTime, OnHand, AmountWithDrawn, AmountDeposited, NewOnhand) values ('06-jan-2021 08:15', 900, 200, 0, 700);

insert into transactions (aDateTime, OnHand, AmountWithDrawn, AmountDeposited, NewOnhand) values ('01-feb-2021 08:15', 700, 0, 1000, 1700);

insert into transactions (aDateTime, OnHand, AmountWithDrawn, AmountDeposited, NewOnhand) values ('09-feb-2021 08:15', 1700, 200, 0, 1500);

insert into transactions (aDateTime, OnHand, AmountWithDrawn, AmountDeposited, NewOnhand) values ('10-feb-2021 08:15', 1500, 300, 0, 1200);

insert into transactions (aDateTime, OnHand, AmountWithDrawn, AmountDeposited, NewOnhand) values ('01-mar-2021 08:15', 1200, 0, 1000, 2200);

insert into transactions (aDateTime, OnHand, AmountWithDrawn, AmountDeposited, NewOnhand) values ('07-mar-2021 08:15', 2200, 400, 0, 1800);

insert into transactions (aDateTime, OnHand, AmountWithDrawn, AmountDeposited, NewOnhand) values ('11-mar-2021 08:15', 1800, 500, 0, 1300);

列表:

select * from transactions order by id

enter image description here

现在我们要按月分组:

select distinct month(adatetime) aMonth, sum(amountWithDrawn) SumWithDrawn, sum(amountDeposited) SumDeposited from transactions group by month(adatetime);

enter image description here

但是我们如何在查询中获得 Onhand 和 NewOnhand?

with cte as
(select distinct month(adatetime) aMonth, sum(amountWithDrawn) SumWithDrawn, sum(amountDeposited) SumDeposited, min(id) MinId, max(id) MaxId from transactions group by month(adatetime)) 
select aMonth, (select Onhand from transactions where id = minid) FirstOnhand, SumWithDrawn, SumDeposited, (select NewOnhand from transactions where id = maxid) LastNewOnhand from cte  

enter image description here

这种方式非常有效(为 ID 添加索引)并且代码非常易于阅读和理解。