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


NTILE (Transact-SQL)

Относится к:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsАналитическая платформа (PDW)SQL база данных в Microsoft Fabric

Распределяет строки упорядоченной секции в заданное количество групп. Группы нумеруются, начиная с единицы. Для каждой строки NTILE возвращается число группы, к которой принадлежит строка.

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

Синтаксис

NTILE (integer_expression) OVER ( [ <partition_by_clause> ] <order_by_clause> )

Аргументы

integer_expression

Положительное целочисленное выражение, указывающее количество групп, в которые необходимо разделить каждую секцию. integer_expression может иметь тип int или bigint.

<partition_by_clause>

Делит результирующий набор, созданный предложением FROM и JOIN, APPLY, PIVOT на разделы, к которым применяется функция. Синтаксис см. в предложении PARTITION BYSELECT — OVER.

<order_by_clause>

Определяет порядок NTILE назначения значений строкам в секции. Целое число не может представлять столбец, если <order_by_clause> используется в функции ранжирования.

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

bigint

Замечания

Если количество строк в секции не делится по integer_expression, это приводит к группам двух размеров, которые отличаются одним элементом. Более крупные группы приходят до небольших групп в порядке, указанном предложением OVER . Например, если общее число строк равно 53, а количество групп — пять, первые три группы имеют 11 строк, а остальные группы имеют 10 строк. Если с другой стороны общее количество строк делится по количеству групп, строки равномерно распределяются между группами. Например, если общее число строк равно 50, и есть пять групп, каждый контейнер содержит 10 строк.

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

Примеры

Примеры кода в этой статье используют AdventureWorks2025 базу данных или AdventureWorksDW2025 пример базы данных, которую можно скачать на домашней странице microsoft SQL Server Samples and Community Projects .

Замечание

В следующих примерах функция CONVERT используется для форматирования SalesYTD данных в виде валюты.

А. Разделение строк на группы

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

USE AdventureWorks2022;
GO

SELECT p.FirstName,
       p.LastName,
       NTILE(4) OVER (ORDER BY SalesYTD DESC) AS Quartile,
       CONVERT (NVARCHAR (20), s.SalesYTD, 1) AS 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;
GO

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

FirstName      LastName              Quartile  SalesYTD       PostalCode
-------------  --------------------- --------- -------------- ----------
Linda          Mitchell              1         4,251,368.55   98027
Jae            Pak                   1         4,116,871.23   98055
Michael        Blythe                1         3,763,178.18   98027
Jillian        Carson                1         3,189,418.37   98027
Ranjit         Varkey Chudukatil     2         3,121,616.32   98055
José           Saraiva               2         2,604,540.72   98055
Shu            Ito                   2         2,458,535.62   98055
Tsvi           Reiter                2         2,315,185.61   98027
Rachel         Valdez                3         1,827,066.71   98055
Tete           Mensa-Annan           3         1,576,562.20   98055
David          Campbell              3         1,573,012.94   98055
Garrett        Vargas                4         1,453,719.47   98027
Lynn           Tsoflias              4         1,421,810.92   98055
Pamela         Ansman-Wolfe          4         1,352,577.13   98027

B. Разделение результирующих наборов с помощью PARTITION BY

В следующем примере к коду из примера A добавляется аргумент PARTITION BY. Строки вначале разделяются по столбцу PostalCode, а затем разделяются на четыре группы для каждого значения PostalCode. В этом примере также объявляется переменная @NTILE_Var, которая используется для указания значения параметра integer_expression.

USE AdventureWorks2022;
GO

DECLARE @NTILE_Var AS INT = 4;

SELECT p.FirstName,
       p.LastName,
       NTILE(@NTILE_Var) OVER (PARTITION BY PostalCode ORDER BY SalesYTD DESC) AS Quartile,
       CONVERT (NVARCHAR (20), s.SalesYTD, 1) AS 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;
GO

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

FirstName    LastName             Quartile SalesYTD      PostalCode
------------ -------------------- -------- ------------  ----------
Linda        Mitchell             1        4,251,368.55  98027
Michael      Blythe               1        3,763,178.18  98027
Jillian      Carson               2        3,189,418.37  98027
Tsvi         Reiter               2        2,315,185.61  98027
Garrett      Vargas               3        1,453,719.47  98027
Pamela       Ansman-Wolfe         4        1,352,577.13  98027
Jae          Pak                  1        4,116,871.23  98055
Ranjit       Varkey Chudukatil    1        3,121,616.32  98055
José         Saraiva              2        2,604,540.72  98055
Shu          Ito                  2        2,458,535.62  98055
Rachel       Valdez               3        1,827,066.71  98055
Tete         Mensa-Annan          3        1,576,562.20  98055
David        Campbell             4        1,573,012.94  98055
Lynn         Tsoflias             4        1,421,810.92  98055

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

В. Разделение строк на группы

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

-- Uses AdventureWorks
SELECT e.LastName,
       NTILE(4) OVER (ORDER BY SUM(SalesAmountQuota) DESC) AS Quartile,
       CONVERT (VARCHAR (13), SUM(SalesAmountQuota), 1) AS SalesQuota
FROM dbo.DimEmployee AS e
     INNER JOIN dbo.FactSalesQuota AS sq
         ON e.EmployeeKey = sq.EmployeeKey
WHERE sq.CalendarYear = 2003
      AND SalesTerritoryKey IS NOT NULL
      AND SalesAmountQuota <> 0
GROUP BY e.LastName
ORDER BY Quartile, e.LastName;

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

LastName          Quartile SalesYTD
----------------- -------- ------------
Blythe            1        4,716,000.00
Carson            1        4,350,000.00
Mitchell          1        4,682,000.00
Pak               1        5,142,000.00
Varkey Chudukatil 1        2,940,000.00
Ito               2        2,644,000.00
Saraiva           2        2,293,000.00
Vargas            2        1,617,000.00
Ansman-Wolfe      3        1,183,000.00
Campbell          3        1,438,000.00
Mensa-Annan       3        1,481,000.00
Valdez            3        1,294,000.00
Abbas             4          172,000.00
Albert            4          651,000.00
Jiang             4          544,000.00
Tsoflias          4          867,000.00

D. Разделение результирующих наборов с помощью PARTITION BY

В следующем примере аргумент добавляется PARTITION BY в код в примере A. Строки сначала секционируются SalesTerritoryCountry , а затем делятся на две группы в каждой группе SalesTerritoryCountry. В ORDER BYOVER предложении упорядочивается и NTILEORDER BY инструкция заказывает SELECT результирующий набор.

-- Uses AdventureWorks
SELECT e.LastName,
       NTILE(2) OVER (PARTITION BY e.SalesTerritoryKey ORDER BY SUM(SalesAmountQuota) DESC) AS Quartile,
       CONVERT (VARCHAR (13), SUM(SalesAmountQuota), 1) AS SalesQuota,
       st.SalesTerritoryCountry
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 sq.CalendarYear = 2003
GROUP BY e.LastName, e.SalesTerritoryKey, st.SalesTerritoryCountry
ORDER BY st.SalesTerritoryCountry, Quartile;

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

LastName          Quartile SalesYTD       SalesTerritoryCountry
----------------- -------- -------------- ------------------
Tsoflias          1           867,000.00   Australia
Saraiva           1         2,293,000.00   Canada
Varkey Chudukatil 1         2,940,000.00   France
Valdez            1         1,294,000.00   Germany
Alberts           1           651,000.00   NA
Jiang             1           544,000.00   NA
Pak               1         5,142,000.00   United Kingdom
Mensa-Annan       1         1,481,000.00   United States
Campbell          1         1,438,000.00   United States
Reiter            1         2,768,000.00   United States
Blythe            1         4,716,000.00   United States
Carson            1         4,350,000.00   United States
Mitchell          1         4,682,000.00   United States
Vargas            2         1,617,000.00   Canada
Abbas             2           172,000.00   NA
Ito               2         2,644,000.00   United States
Ansman-Wolfe      2         1,183,000.00   United States