• 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