在SQL中选择具有多个GROUP的表中的TOP 2值的SUM

ale*_*ila 9 sql sql-server sql-server-2000 set

我一直在使用SQL Server 2000中的集合,并为我的一个临时表(#Periods)提供以下表格结构:

    RestCTR     HoursCTR    Duration    Rest
    ----------------------------------------
    1           337         2           0
    2           337         46          1
    3           337         2           0
    4           337         46          1
    5           338         1           0
    6           338         46          1
    7           338         2           0
    8           338         46          1
    9           338         1           0
    10          339         46          1
    ...

我想要做的是计算每个HoursCTR的2个最长休息时间的总和,最好使用集合和临时表(而不是游标或嵌套子查询).

这是在SQL中无法运行的梦想查询(无论我运行多少次):

Select HoursCTR, SUM ( TOP 2 Duration ) as LongestBreaks
FROM #Periods
WHERE Rest = 1
Group By HoursCTR    
Run Code Online (Sandbox Code Playgroud)

HoursCTR可以具有任意数量的休息期(包括无).

我目前的解决方案不是很优雅,基本上涉及以下步骤:

  1. 获取休息的最长持续时间,按HoursCTR分组
  2. 选择返回每个HoursCTR的最大持续时间的第一个(最小)RestCTR行
  3. 重复步骤1(不包括步骤2中已收集的行)
  4. 重复步骤2(再次,排除在步骤2中收集的行)
  5. 将RestCTR行(从步骤2和4)组合到单个表中
  6. 获取步骤5中行指向的持续时间的和,按HoursCTR分组

如果有任何设置功能可以减少这个过程,那么它们将非常受欢迎.

Bil*_*win 7

在SQL Server中执行此操作的最佳方法是使用公用表表达式,使用窗口函数对每个组中的行进行编号ROW_NUMBER():

WITH NumberedPeriods AS (
  SELECT HoursCTR, Duration, ROW_NUMBER() 
    OVER (PARTITION BY HoursCTR ORDER BY Duration DESC) AS RN
  FROM #Periods
  WHERE Rest = 1
)
SELECT HoursCTR, SUM(Duration) AS LongestBreaks
FROM NumberedPeriods
WHERE RN <= 2
GROUP BY HoursCTR
Run Code Online (Sandbox Code Playgroud)

编辑:我在分区中添加了一个ORDER BY子句,以获得两个最长的休止符.


Mea culpa,我没注意到你需要在Microsoft SQL Server 2000中使用它.该版本不支持CTE或窗口函数.我会留下上面的答案,以防它帮助其他人.

在SQL Server 2000中,常见的建议是使用相关的子查询:

SELECT p1.HoursCTR, (SELECT SUM(t.Duration) FROM 
    (SELECT TOP 2 p2.Duration FROM #Periods AS p2
     WHERE p2.HoursCTR = p1.HoursCTR 
     ORDER BY p2.Duration DESC) AS t) AS LongestBreaks
FROM #Periods AS p1
Run Code Online (Sandbox Code Playgroud)

  • OP表示SQL Server 2000.ROW_NUMBER()和CTE不可用. (2认同)