Assuming you are using SQL Server 2005 or higher, using CTE will do the trick.
- Attach
ROW_NUMBER to each row, starting with the highest value, resetting for each month. SELECT top 2 rows for each month from this query (rownumber <= 2)UNION with the remaining rows (rownumber> 2)
SQL statement
;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
Kudo go to Andrey to teach me new tricks.
source share