There is a simpler way.
No updates required:
--===== Create a test table.
-- This is NOT part of the solution.
IF OBJECT_ID('TempDB..#ST') IS NOT NULL DROP TABLE #ST
DECLARE @N int
SET @N = 3 -- how many rows to retrieve for each group
--create the temp table, with Identity column playing the role of RowNumber
select
identity(int,1,1) AS ID,
territoryID, salesPersonID, SalesTotal
INTO #ST
from (select
TerritoryID,
salesPersonID,
sum(TotalDue) as salesTotal
from [Sales].[SalesOrderHeader]
where SalesPersonID is not null
group by TerritoryID, SalesPersonID ) ST
ORDER BY TerritoryID,
salesTotal DESC -- arranging ID's within the each group
SELECT T.*
FROM #ST T
INNER JOIN (
SELECT TerritoryID,
MIN(ID) FromID, MIN(ID) + @N ToID
--MIN(ID) is a starting point for rowcount within each group
FROM #ST
GROUP BY TerritoryID
) DT ON DT.TerritoryID = T.TerritoryID
AND T.ID BETWEEN DT.FromID AND DT.ToID
ORDER BY T.TerritoryID, T.ID
_____________
Code for TallyGenerator