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

dow*_*oad 7 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   
Run Code Online (Sandbox Code Playgroud)

我需要获得列开始的第一个值和列的最后一个值以组列的组结束

结果表应如下所示

   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  
Run Code Online (Sandbox Code Playgroud)

我做了查询,但有First_valueLAST_VALUEover (partition by)它的工作sql server 2012,但没有工作,sql server 2008我需要一个查询,可以在执行sql server 2008

谢谢

Fel*_*tan 9

如何使用ROW_NUMBER:

SQL小提琴

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
Run Code Online (Sandbox Code Playgroud)

  • 如果您的表很小或者每组的元素数量很少,使用“ROW_NUMBER”的解决方案可以有效地工作。如果您的表很大并且每个组的元素数量很大,并且您有一个单独的表,其中包含所有组“ID”的列表,那么具有适当索引的“CROSS APPLY”会更有效。例如,您的表有 100M 行,但只有 10K 个组。“ROW_NUMBER”必须读取所有 100M 行,计算所有行的行号(在建议的解决方案中很可能两次),然后放弃大部分工作,而您实际上只需要读取 20K 行。 (2认同)

Bri*_*lia 5

这是一种方式——

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);
Run Code Online (Sandbox Code Playgroud)

小提琴: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)
Run Code Online (Sandbox Code Playgroud)