T-SQL Ninja #13

DENSE_RANK

What is DENSE_RANK?

In the last two weeks we have already given you “joy” by numbering rows in the result set with the ROW_NUMBER and RANK functions. We want to continue with this today. The DENSE_RANK function is, as the name suggests, closely related to the RANK function from last week. So what is the difference? It’s relatively simple: while the RANK function skips a number when assigning the same number for two lines, the DENSE_RANK function skips nothing, so here you get a continuous sequence of numbers.

How can you work with DENSE_RANK?

Remember the query we used last week using the RANK function. We created a query in the Wide World Importers database that returns sortable items, but the sorting does not have to be unique. We used a CTE to count the number of orders in which each product appeared in the OrderLines and calculated the popularity of the respective product with the RANK function:

WITH cte_sales AS (
    SELECT 
         StockItemID
        ,COUNT(*) AS nOrders
        ,SUM(Quantity*UnitPrice) AS TotalSales 
    FROM 
        Sales.OrderLines
    GROUP BY StockItemID
)
SELECT  
     StockItemID
    ,nOrders
    ,TotalSales
    ,ROW_NUMBER() OVER (ORDER BY nOrders DESC, TotalSales DESC) as Popularity
    ,RANK() OVER (ORDER BY nOrders DESC) as Real_Popularity
FROM cte_sales 
ORDER BY 
     nOrders DESC
    ,TotalSales DESC

As a result, both products, 104 and 120 had received the (real) popularity 1, while the next product (the one with ID 167) was assigned the third place, similar to what is usual in sports competitions.

Now, in order not to skip a rank, we add another column to the query:

WITH cte_sales AS (
    SELECT 
         StockItemID
        ,COUNT(*) AS nOrders
        ,SUM(Quantity*UnitPrice) AS TotalSales 
    FROM 
        Sales.OrderLines
    GROUP BY StockItemID
)
SELECT  
     StockItemID
    ,nOrders
    ,TotalSales
    ,ROW_NUMBER() OVER (ORDER BY nOrders DESC, TotalSales DESC) as Popularity
    ,RANK() OVER (ORDER BY nOrders DESC) as Real_Popularity
    ,DENSE_RANK() OVER (ORDER BY nOrders DESC) as Dense_Real_Popularity
FROM cte_sales 
ORDER BY 
     nOrders DESC
    ,TotalSales DESC

In the result set, the product 167 now has the Dense_Real_Popularity 2 instead of the Real_Popularity 3. And to round things up, let’s take a look at the most popular items:

WITH cte_sales AS (
    SELECT 
         StockItemID
        ,COUNT(*) AS nOrders
        ,SUM(Quantity*UnitPrice) AS TotalSales 
    FROM 
        Sales.OrderLines
    GROUP BY StockItemID
)
SELECT  
     cs.StockItemID
    ,si.StockItemName
    ,nOrders
    ,TotalSales
    ,ROW_NUMBER() OVER (ORDER BY nOrders DESC, TotalSales DESC) as Popularity
    ,RANK() OVER (ORDER BY nOrders DESC) as Real_Popularity
    ,DENSE_RANK() OVER (ORDER BY nOrders DESC) as Dense_Real_Popularity
FROM cte_sales cs 
LEFT JOIN 
    Warehouse.StockItems si 
ON cs.StockItemID = si.StockItemID
ORDER BY 
     nOrders DESC
    ,TotalSales DESC

So it was green battery-operated slippers and a hoodie with an alien officer that were particularly popular with Wide World Importers’ customers. The ninja in us would have guessed Shuriken, after all, these are expendable items…

References

Ninja-Notebooks @ GitHub

Leave a Reply

Your email address will not be published. Required fields are marked *