T-SQL Ninja #13

DENSE_RANK

Was ist DENSE_RANK?

In den letzten beiden Wochen haben wir euch bereits mit dem Durchnummerieren von Zeilen der Ergebnismenge mit den ROW_NUMBER und RANK-Funktionen „Freude“ bereitet. Damit wollen wir auch heute noch fortfahren. Die DENSE_RANK-Funktion ist, wie es der Name schon andeutet, eng mit der RANK-Funktion aus der letzten Woche verbunden. Was ist also der Unterschied? Das ist relativ einfach gesagt: während die RANK-Funktion nämlich bei der Vergabe gleicher Nummern für zwei Zeilen eine Nummer überspringt, überspringt die DENSE_RANK Funktion nichts, hier erhaltet ihr also eine fortlaufende Sequenz an Nummern.

Wie könnt ihr mit DENSE_RANK arbeiten?

Erinnert euch an die Abfrage, mit der wir in der letzten Woche die RANK Funktion verwendet haben. Dafür haben wir wir uns nun in der Wide World Importers Datenbank eine Abfrage erstelt, die sortierbare Artikel liefert, bei denen die Sortierung aber nicht eindeutig sein muss. Dafür verwendeten wir eine CTE mit der wir aus den OrderLines die Anzahl der Bestellungen zählten, in denen jedes Produkt auftauchte und errechneten mit der RANK-Funktion eine Popularität des jeweiligen Produkts:

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

Im Resultat hatten beide Produkte, 104 und 120 die (echte) Popularität 1 erhalten, während dem nächsten Produkt (dem mit der ID 167), ähnlich wie das bei Sportwettkämpfen üblich ist, der dritte Rang zugewiesen wurde.

Um nun keinen Rang mehr zu überspringen, fügen wir noch eine weitere Spalte zur Abfrage hinzu:

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 der Ergebnismenge hat das Produkt 167 nun die Dense_Real_Popularity 2 statt der Real_Popularity 3. Und um die Sache nun noch abzurunden, schauen wir doch noch, um welche Items es sich bei den populärsten Items gehandelt hat:

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

Es waren also grüne batteriebetriebene Hausschuhe und ein Hoodie mit einem Alien Offizier besonders populär bei der Kundschaft von Wide World Importers. Der Ninja in uns hätte ja auf Shuriken getippt, immerhin sind das Verbrauchsgegenstände…

Referenzen

Ninja-Notebooks @ GitHub

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.