Tsql t-sql按类别分组并获取前n个值

Tsql t-sql按类别分组并获取前n个值,tsql,Tsql,假设我有一张桌子: Month | Person | Value ---------------------- Jan | P1 | 1 Jan | P2 | 2 Jan | P3 | 3 Feb | P1 | 5 Feb | P2 | 4 Feb | P3 | 3 Feb | P4 | 2 ... 我如何构建一个t-sql查询来获取前2个值行和第三个值行以及其他值行的总和 大概是这样的: RESULT: M

假设我有一张桌子:

Month | Person | Value
----------------------
Jan   | P1     | 1
Jan   | P2     | 2
Jan   | P3     | 3
Feb   | P1     | 5
Feb   | P2     | 4
Feb   | P3     | 3
Feb   | P4     | 2
...
我如何构建一个t-sql查询来获取前2个值行和第三个值行以及其他值行的总和

大概是这样的:

RESULT: 
Month | Person | Value
----------------------
Jan   | P3     | 3
Jan   | P2     | 2
Jan   | Others | 1 -(sum of the bottom value - in this case (Jan, P1, 1))
Feb   | P1     | 5
Feb   | P2     | 4
Feb   | Others | 5 -(sum of the bottom values - in this case (Feb, P3, 3) and (Feb, P4, 2))

谢谢

假设您使用的是SQL Server 2005或更高版本,那么使用CTE就可以了

将行号附加到每行,从最高值开始,每月重置。 从该查询第2行中为每个月选择前2行 SQL语句


工藤去安德烈教我一些新把戏。

@Andriy:你不可能把它们都拥有。。。如果我没有弄错的话,OP需要前2个值行,我也忽略了它。人的订单应该变成价值的订单。@Lieven:看来我们都忽略了这一点。专家们……我相信你在CTE中指的是按价值排序,否则它会起作用,+1。@Andrey M:我为什么要按价值排序?好吧,这些值可以是任何东西。根据OP的需要,最终的ORDER BY可能会发生变化,因此我集中精力获取正确的数据行,使用ORDER BY只是为了提高可读性。@Andriy M:好的,我明白了,OP需要前两个值。我将更改我的帖子。安德烈的意思是行数函数中的顺序,而不是结果。
;WITH Months (Month, Person, Value) AS (
  SELECT 'Jan', 'P1', 1 UNION ALL
  SELECT 'Jan', 'P2', 2 UNION ALL
  SELECT 'Jan', 'P3', 3 UNION ALL
  SELECT 'Feb', 'P1', 5 UNION ALL
  SELECT 'Feb', 'P2', 4 UNION ALL
  SELECT 'Feb', 'P3', 3 UNION ALL
  SELECT 'Feb', 'P4', 2
),
q AS (
  SELECT  Month
          , Person
          , Value
          , RowNumber = ROW_NUMBER() OVER (PARTITION BY Month ORDER BY Value DESC)
  FROM    Months
)
SELECT  Month
        , Person
        , Value
FROM    (        
          SELECT  Month
                  , Person
                  , Value
                  , RowNumber
          FROM    q
          WHERE   RowNumber <= 2 
          UNION ALL
          SELECT  Month
                  , Person = 'Others'
                  , SUM(Value)
                  , MAX(RowNumber)
          FROM    q
          WHERE   RowNumber > 2        
          GROUP BY
                  Month 
        ) q                          
ORDER BY
        Month DESC
        , RowNumber
WITH NTable AS
(
    SELECT [Month],
                   Person,
                   Value,
                   ROW_NUMBER() OVER (PARTITION BY [Month] ORDER BY Value DESC) 
                       AS Rownumber 
            FROM MyTable
)
SELECT  t.[Month], 
        CASE Rownumber WHEN 1 THEN t.Person WHEN 2 THEN t.Person ELSE 'Others' END As Person, 
        SUM(t.Value) As [Sum] 
FROM NTable t
GROUP BY t.[Month], CASE Rownumber WHEN 1 THEN t.Person WHEN 2 THEN t.Person ELSE 'Others' END
ORDER BY t.[Month]
;WITH atable (Month, Person, Value) AS (
  SELECT 'Jan', 'P1', 1 UNION ALL
  SELECT 'Jan', 'P2', 2 UNION ALL
  SELECT 'Jan', 'P3', 3 UNION ALL
  SELECT 'Feb', 'P1', 5 UNION ALL
  SELECT 'Feb', 'P2', 4 UNION ALL
  SELECT 'Feb', 'P3', 3 UNION ALL
  SELECT 'Feb', 'P4', 2
),
numbered AS (
  SELECT
    Month, Person, Value,
    rownum = ROW_NUMBER() OVER (PARTITION BY Month ORDER BY Value DESC)
  FROM atable
),
grouped AS (
  SELECT
    Month, Person, Value,
    Grp = CASE WHEN rownum < 3 THEN rownum ELSE 3 END
  FROM numbered
)
SELECT
  Month,
  Person = CASE Grp WHEN 3 THEN 'Others' ELSE MAX(Person) END,
  Value = SUM(Value)
FROM grouped
GROUP BY Month, Grp
ORDER BY Month DESC, Grp