NTILE (Transact-SQL)

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse AnalyticsAnalytics Platform System (PDW)

将有序分区中的行分发到指定数目的组中。 各个组有编号,编号从一开始。 对于每一行, 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 BY有关语法,请参阅 SELECT - OVER 子句

order_by_clause<>

确定将值分配给分区中的行的顺序 NTILE 。 在排名函数中使用order_by_clause>时<,整数不能表示列。

返回类型

bigint

备注

如果分区中的行数因 integer_expression不可见,这会导致由一个成员组成的两个大小组。 较大的组按子句指定的 OVER 顺序出现在较小的组之前。 例如,如果总行数为 53,组数为 5,则前三个组有 11 行,其余两个组各有 10 行。 另一方面,如果行总数由组数分割,则行在组之间均匀分布。 例如,如果总行数为 50,并且有五个组,则每个存储桶包含 10 行。

NTILE 是不确定的。 有关详细信息,请参阅 “确定性”和“不确定”函数

示例

本文中的代码示例使用 AdventureWorks2022AdventureWorksDW2022 示例数据库,可以从 Microsoft SQL Server 示例和社区项目 主页下载该数据库。

注释

在以下示例中, CONVERT 函数用于将数据 SalesYTD 格式化为货币。

A. 将行划分为组

下面的示例根据员工的年初至今销售额将行分到四个员工组中。 由于总行数与组数不可见,前两个组有四行,其余组各有三行。

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 将结果集除以

以下示例将 PARTITION BY 参数添加到示例 A 中的代码。首先按 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 和 Analytics Platform System (PDW)

C. 将行划分为组

以下示例使用 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组中的两个组。 OVERORDER BY句对结果集进行排序NTILEORDER BYSELECT语句排序。

-- 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