Similar to the RANK function, you use the DENSE_RANK function to return the rank of the value in the current row as compared to the value in other rows. The rank of a value reflects the order in which it would appear if the list of values were sorted. Rank is calculated for the expression specified in the window's ORDER BY clause.
The DENSE_RANK function returns a series of ranks that are monotonically increasing with no gaps, or jumps in rank value. The term dense is used because there are no jumps in rank value (unlike the RANK function).
As the window moves down the input rows, the rank is calculated for the expression specified in the window's ORDER BY clause. If the ORDER BY clause includes multiple expressions, the second and subsequent expressions are used to break ties if the first expression has the same value in adjacent rows. NULL values are sorted before any other value (in ascending sequence).
The following query determines the three most expensive products in the database. A descending sort sequence is specified for the window so that the most expensive products have the lowest rank (rankings start at 1).
SELECT Top 3 * FROM ( SELECT Description, Quantity, UnitPrice, DENSE_RANK( ) OVER ( ORDER BY UnitPrice DESC ) AS Rank FROM Products ) AS DT ORDER BY Rank; |
This query returns the following result:
Description | Quantity | UnitPrice | Rank | |
---|---|---|---|---|
1 | Hooded Sweatshirt | 39 | 24.00 | 1 |
2 | Zipped Sweatshirt | 32 | 24.00 | 1 |
3 | Cotton Shorts | 80 | 15.00 | 2 |
Note that rows 1 and 2 have the same value for Unit Price, and therefore also have the same rank. This is called a tie.
With the DENSE_RANK function, there is no jump in the rank value after a tie. For example, the rank value for row 3 is 2. This is different from the RANK function, where a jump in rank values occurs after a tie. See RANK function.
Because windows are evaluated after a query's GROUP BY clause, you can specify complex requests that determine rankings based on the value of an aggregate function.
The following query produces the top three salespeople in each region by their total sales within that region, along with the total sales for each region:
SELECT * FROM ( SELECT o.SalesRepresentative, o.Region, SUM( s.Quantity * p.UnitPrice ) AS total_sales, DENSE_RANK( ) OVER ( PARTITION BY o.Region, GROUPING( o.SalesRepresentative ) ORDER BY total_sales DESC ) AS sales_rank FROM Products p, SalesOrderItems s, SalesOrders o WHERE p.ID = s.ProductID AND s.ID = o.ID GROUP BY GROUPING SETS( ( o.SalesRepresentative, o.Region ), o.Region ) ) AS DT WHERE sales_rank <= 3 ORDER BY Region, sales_rank; |
This query returns the following result:
SalesRepresentative | Region | total_sales | sales_rank | |
---|---|---|---|---|
1 | 299 | Canada | 9312.00 | 1 |
2 | (NULL) | Canada | 24768.00 | 1 |
3 | 1596 | Canada | 3564.00 | 2 |
4 | 856 | Canada | 2724.00 | 3 |
5 | 299 | Central | 32592.00 | 1 |
6 | (NULL) | Central | 134568.00 | 1 |
7 | 856 | Central | 14652.00 | 2 |
8 | 467 | Central | 14352.00 | 3 |
9 | 299 | Eastern | 21678.00 | 1 |
10 | (NULL) | Eastern | 142038.00 | 1 |
11 | 902 | Eastern | 15096.00 | 2 |
12 | 690 | Eastern | 14808.00 | 3 |
13 | 1142 | South | 6912.00 | 1 |
14 | (NULL) | South | 45262.00 | 1 |
15 | 667 | South | 6480.00 | 2 |
16 | 949 | South | 5782.00 | 3 |
17 | 299 | Western | 5640.00 | 1 |
18 | (NULL) | Western | 37632.00 | 1 |
19 | 1596 | Western | 5076.00 | 2 |
20 | 667 | Western | 4068.00 | 3 |
This query combines multiple groupings through the use of GROUPING SETS. Hence, the WINDOW PARTITION clause for the window uses the GROUPING function to distinguish between detail rows that represent particular salespeople and the subtotal rows that list the total sales for an entire region. The subtotal rows by region, which have the value NULL for the sales rep attribute, each have the ranking value of 1 because the result's ranking order is restarted with each partition of the input; this ensures that the detail rows are ranked correctly starting at 1.
Finally, note in this example that the DENSE_RANK function ranks the input over the aggregation of the total sales. An aliased select list item is used as a shorthand in the WINDOW ORDER clause.
For more information about the syntax for the DENSE_RANK function, see DENSE_RANK function [Ranking].
Send feedback about this page via email or DocCommentXchange | Copyright © 2008, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.0 |