Поделиться через


DENSE_RANK (Transact-SQL)

Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure конечной точке аналитики платформы Аналитики Azure Synapse Analytics (PDW) в Microsoft Fabric Хранилище в Microsoft Fabric

Эта функция возвращает ранг каждой строки в секции результирующего набора без промежутков в значениях ранжирования. Ранг определенной строки равен количеству различных значений рангов, предшествующих строке, увеличенному на единицу.

Соглашения о синтаксисе Transact-SQL

Синтаксис

DENSE_RANK ( ) OVER ( [ <partition_by_clause> ] < order_by_clause > )  

Аргументы

<partition_by_clause>
Делит результирующий набор, полученный с помощью предложения FROM, на секции, к которым затем применяется функция DENSE_RANK. Синтаксис PARTITION BY см. в статье Предложение OVER (Transact-SQL).

<order_by_clause>
Определяет порядок, в котором функция DENSE_RANK применяется к строкам в секции.

Типы возвращаемых данных

bigint

Замечания

Если две строки или несколько в одной секции имеют одинаковые значения ранга, каждой такой строке присваивается один и тот же ранг. Например, если двум лучшим менеджерам по продажам соответствует одинаковое значение SalesYTD, им обоим присваивается значение ранга 1. Менеджеру по продажам со следующим по величине значением SalesYTD присваивается значение ранга 2. Это значение превышает количество отдельных строк, предшествующих данной строке, на единицу. Таким образом, между номерами, возвращаемыми функцией DENSE_RANK, нет промежутков, и они всегда имеют последовательные значения ранга.

Порядок сортировки, используемый для всего запроса, определяет порядок строк в результирующем наборе. Из этого следует, что строка с рангом 1 не всегда является первой строкой в секции.

Функция DENSE_RANK не детерминирована. Дополнительные сведения см. в статье Детерминированные и недетерминированные функции.

Примеры

А. Ранжирование строк внутри секции

В приведенном ниже примере продукты ранжируются по количеству в указанных местоположениях в описи. Функция DENSE_RANK секционирует результирующий набор по LocationID и логически сортирует его по Quantity. Обратите внимание, что количество продуктов 494 и 495 совпадает. Так как они имеют одинаковое значение количества, им обоим присваивается значение ранга 1.

USE AdventureWorks2022;  
GO  
SELECT i.ProductID, p.Name, i.LocationID, i.Quantity  
    ,DENSE_RANK() OVER   
    (PARTITION BY i.LocationID ORDER BY i.Quantity DESC) AS Rank  
FROM Production.ProductInventory AS i   
INNER JOIN Production.Product AS p   
    ON i.ProductID = p.ProductID  
WHERE i.LocationID BETWEEN 3 AND 4  
ORDER BY i.LocationID;  
GO  

Вот результирующий набор.

ProductID   Name                               LocationID Quantity Rank  
----------- ---------------------------------- ---------- -------- -----  
494         Paint - Silver                     3          49       1  
495         Paint - Blue                       3          49       1  
493         Paint - Red                        3          41       2  
496         Paint - Yellow                     3          30       3  
492         Paint - Black                      3          17       4  
495         Paint - Blue                       4          35       1  
496         Paint - Yellow                     4          25       2  
493         Paint - Red                        4          24       3  
492         Paint - Black                      4          14       4  
494         Paint - Silver                     4          12       5  
  
(10 row(s) affected)  
  

B. Ранжирование всех строк в результирующем наборе

В приведенном ниже примере возвращается список первых десяти сотрудников, ранжированных по окладу. Так как в инструкции SELECT предложение PARTITION BY не указывалось, функция DENSE_RANK применялась ко всем строкам результирующего набора.

USE AdventureWorks2022;  
GO  
SELECT TOP(10) BusinessEntityID, Rate,   
       DENSE_RANK() OVER (ORDER BY Rate DESC) AS RankBySalary  
FROM HumanResources.EmployeePayHistory;  

Вот результирующий набор.

BusinessEntityID Rate                  RankBySalary  
---------------- --------------------- --------------------  
1                125.50                1  
25               84.1346               2  
273              72.1154               3  
2                63.4615               4  
234              60.0962               5  
263              50.4808               6  
7                50.4808               6  
234              48.5577               7  
285              48.101                8  
274              48.101                8  

C. Использование четырех ранжирующих функций в одном запросе

В этом примере демонстрируются четыре функции ранжирования:

Они используются в одном запросе. См. конкретные примеры по каждой ранжирующей функции.

USE AdventureWorks2022;  
GO  
SELECT p.FirstName, p.LastName  
    ,ROW_NUMBER() OVER (ORDER BY a.PostalCode) AS "Row Number"  
    ,RANK() OVER (ORDER BY a.PostalCode) AS Rank  
    ,DENSE_RANK() OVER (ORDER BY a.PostalCode) AS "Dense Rank"  
    ,NTILE(4) OVER (ORDER BY a.PostalCode) AS Quartile  
    ,s.SalesYTD  
    ,a.PostalCode  
FROM Sales.SalesPerson AS s   
    INNER JOIN Person.Person AS p   
        ON s.BusinessEntityID = p.BusinessEntityID  
    INNER JOIN Person.Address AS a   
        ON a.AddressID = p.BusinessEntityID  
WHERE TerritoryID IS NOT NULL AND SalesYTD <> 0;  

Вот результирующий набор.

FirstName LastName Номер строки Rank Dense Rank Quartile SalesYTD PostalCode
Николай Blythe 1 1 1 1 4557045,0459 98027
Лиза Mitchell 2 1 1 1 5200475,2313 98027
Jillian Carson 3 1 1 1 3857163,6332 98027
Garrett Vargas 4 1 1 1 1764938,9859 98027
Tsvi Reiter 5 1 1 2 2811012,7151 98027
Shu Ito 6 6 2 2 3018725,4858 98055
Josй Saraiva 7 6 2 2 3189356,2465 98055
Дэвид Campbell 8 6 2 3 3587378,4257 98055
Tete Mensa-Annan 9 6 2 3 1931620,1835 98055
Lynn Tsoflias 10 6 2 3 1758385,926 98055
Rachel Valdez 11 6 2 4 2241204,0424 98055
Jae Pak 12 6 2 4 5015682,3752 98055
Ranjit Varkey Chudukatil 13 6 2 4 3827950,238 98055

Примеры: Azure Synapse Analytics и система платформы аналитики (PDW)

Г. Ранжирование строк внутри секции

В приведенном ниже примере торговые представители на каждой территории продаж ранжируются в соответствии с общим объемом продаж. Функция DENSE_RANK секционирует набор строк по SalesTerritoryGroup и логически сортирует результирующий набор по SalesAmountQuota.

-- Uses AdventureWorks  
  
SELECT LastName, SUM(SalesAmountQuota) AS TotalSales, SalesTerritoryGroup,  
    DENSE_RANK() OVER (PARTITION BY SalesTerritoryGroup ORDER BY SUM(SalesAmountQuota) DESC ) AS RankResult  
FROM dbo.DimEmployee AS e  
INNER JOIN dbo.FactSalesQuota AS sq ON e.EmployeeKey = sq.EmployeeKey  
INNER JOIN dbo.DimSalesTerritory AS st ON e.SalesTerritoryKey = st.SalesTerritoryKey  
WHERE SalesPersonFlag = 1 AND SalesTerritoryGroup != N'NA'  
GROUP BY LastName, SalesTerritoryGroup;  

Вот результирующий набор.

 LastName          TotalSales     SalesTerritoryGroup  RankResult  
----------------  -------------  -------------------  --------  
Pak               10514000.0000  Europe               1  
Varkey Chudukatil  5557000.0000  Europe               2  
Valdez             2287000.0000  Europe               3  
Carson            12198000.0000  North America        1  
Mitchell          11786000.0000  North America        2  
Blythe            11162000.0000  North America        3  
Reiter             8541000.0000  North America        4  
Ito                7804000.0000  North America        5  
Saraiva            7098000.0000  North America        6  
Vargas             4365000.0000  North America        7  
Campbell           4025000.0000  North America        8  
Ansman-Wolfe       3551000.0000  North America        9  
Mensa-Annan        2753000.0000  North America        10  
Tsoflias           1687000.0000  Pacific              1 

См. также

RANK (Transact-SQL)
ROW_NUMBER (Transact-SQL)
NTILE (Transact-SQL)
Ранжирование функций (Transact-SQL)
Функции