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…