Search code examples
t-sqlsql-server-2005stored-proceduresranking

Is T-SQL (2005) RANK OVER(PARTITION BY) the answer?


I have a stored procedure that does paging for the front end and is working fine. I now need to modify that procedure to group by four columns of the 20 returned and then only return the row within each group that contains the lowest priority. So when resort_id, bedrooms, kitchen and checkin (date) all match then only return the row that has the min priority. I have to still maintain the paging functionality. The @startIndex and @upperbound are parms passed into the procedure from the front end for paging. I’m thinking that RANK OVER (PARTITION BY) is the answer I just can’t quite figure out how to put it all together.

SELECT I.id,
       I.resort_id,
       I.[bedrooms],
       I.[kitchen],
       I.[checkin],
       I.[priority],
       I.col_1,
       I.col_2 /* ..... (more cols) */
FROM  ( 
        SELECT  ROW_NUMBER() OVER(ORDER by checkin) AS rowNumber, 
        *
        FROM Inventory
      ) AS I  
WHERE  rowNumber >=  @startIndex
AND    rowNumber <   @upperBound
ORDER BY rowNumber

Example 2 after fix:

SELECT I.resort_id,
       I.[bedrooms],
       I.[kitchen],
       I.[checkin],
       I.[priority],
       I.col_1,
       I.col_2 /* ..... (more cols) */
FROM Inventory i 
JOIN 
( 
    SELECT ROW_NUMBER() OVER(ORDER BY h.checkin) as rowNumber, MIN(h.id) as id
    FROM Inventory h
    JOIN (
        SELECT  resort_id, bedrooms, kitchen, checkin, id, MIN(priority) as priority
        FROM Inventory
        GROUP BY resort_id, bedrooms, kitchen, checkin, id
    ) h2 on h.resort_id = h2.resort_id and 
            h.bedrooms = h2.bedrooms and 
            h.kitchen = h2.kitchen and 
            h.checkin = h2.checkin and 
            h.priority = h2.priority
    GROUP BY h.resort_id, h.bedrooms, h.kitchen, h.checkin, h.priority
) AS I2 
    on i.id = i2.id
WHERE  rowNumber >=  @startIndex
AND    rowNumber <   @upperBound
ORDER BY rowNumber

Solution

  • I would accompish it this way.

    SELECT I.resort_id,
           I.[bedrooms],
           I.[kitchen],
           I.[checkin],
           I.[priority],
           I.col_1,
           I.col_2 /* ..... (more cols) */
    FROM Inventory i 
    JOIN 
    ( 
        SELECT ROW_NUMBER(ORDER BY Checkin) as rowNumber, MIN(id) id
        FROM Inventory h
        JOIN (
            SELECT  resort_id, bedrooms, kitchen, checkin id, MIN(priority) as priority
            FROM Inventory
            GROUP BY resort_id, bedrooms, kitchen, checkin
        ) h2 on h.resort_id = h2.resort and 
                h.bedrooms = h2.bedrooms and 
                h.kitchen = h2.kitchen and 
                h.checkin = h2.checkin and 
                h.priority = h2.priority
        GROUP BY h.resort_id, h.bedrooms, h.kitchen, h.checkin, h.priority
    ) AS I2 
        on i.id = i2.id
    WHERE  rowNumber >=  @startIndex
    AND    rowNumber <   @upperBound
    ORDER BY rowNumber