DENSE_RANK (Transact-SQL)

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

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

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

Синтаксис

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

Аргументы

<partition_by_clause>

Делит результирующий набор, полученный с помощью предложения FROM, на секции, к которым затем применяется функция DENSE_RANK. Синтаксис см. в статье PARTITION BY.

<order_by_clause>

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

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

bigint

Замечания

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

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

Функция DENSE_RANK не детерминирована. Дополнительные сведения см. в разделе Deterministic and Nondeterministic Functions.

Для рекомендаций по настройке производительности функций окна см. OVER() Вопросы производительности.

Примеры

А. Ранговые строки внутри разбиения

В приведенном ниже примере продукты ранжируются по количеству в указанных местоположениях в описи. Функция 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  

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

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

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

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 Плотный ранг 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 Варкей Чудукатил 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