{"id":1598,"date":"2013-03-05T00:00:00","date_gmt":"2013-03-05T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/sql-server-2012-window-function-basics\/"},"modified":"2021-09-29T16:21:45","modified_gmt":"2021-09-29T16:21:45","slug":"sql-server-2012-window-function-basics","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/sql-server-2012-window-function-basics\/","title":{"rendered":"SQL Server 2012 Window Function Basics"},"content":{"rendered":"<div id=\"pretty\">\n<p class=\"start\">When Microsoft released SQL Server 2005, they included support for window functions, built-in T-SQL functions that can be applied to a result set&#8217;s partitioned rows-<i>windows<\/i>-in order to rank or aggregate data in each partition. However, support for window functions was fairly limited in SQL Server 2005, and those limitations carried into 2008. But SQL Server 2012 has pushed through those constraints by expanding the capabilities of existing window functions and by adding new functions that support windowing.<\/p>\n<p>SQL Server 2012 now includes three types of window functions: ranking, aggregate, and analytic. Ranking functions return a ranking value for each row in a partition. Aggregate functions perform a calculation on a column&#8217;s values within a partition, such as finding the total or average of those values. Ranking functions first appeared in SQL Server 2005 with the advent of window function support. Aggregate functions have been around forever.<\/p>\n<p>Analytic functions are new to SQL Server 2012. An analytic function computes an aggregate value based on the values in a column within a partition. However, analytic functions go beyond simple aggregate ones by being able to take such actions as returning the first or last value in an ordered partitioned set, retrieving the previous or next value in that set, or calculating percentages based on the set&#8217;s cumulative values.<\/p>\n<div class=\"note\">\n<p class=\"note\">NOTE: For more details about analytic functions, see the topic &#8220;<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/hh213234.aspx\">Analytic Functions (Transact-SQL)<\/a>&#8221; in SQL Server Books Online. Also note that SQL Server 2012 supports another window function, <b><code>NEXT<\/code><\/b> <b><code>VALUE<\/code><\/b> <b><code>FOR<\/code><\/b>, which is not considered a rank, aggregate, or analytic function. The function generates a sequence number based on a specified sequence object. A discussion of the <b><code>NEXT<\/code><\/b> <b><code>VALUE<\/code><\/b> <b><code>FOR<\/code><\/b> function is beyond the scope of this article, but you can find details about the function in the topic &#8220;<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ff878370.aspx\">NEXT VALUE FOR (Transact-SQL)<\/a>&#8221; in SQL Server Books Online.<\/p>\n<\/div>\n<p>The key to understanding SQL Server window functions is in the <b><code>OVER<\/code><\/b> clause, which can be defined on any window function used in a query&#8217;s select list. The clause determines how to partition and sort a result set in order to apply the window function. In fact, you can think of a window function as one that supports the <b><code>OVER<\/code><\/b> clause.<\/p>\n<p>To use the <b><code>OVER<\/code><\/b> clause, you first call the window function, followed by the <b><code>OVER<\/code><\/b> keyword. You then specify one or more of the supported subclauses (enclosed in parentheses) to qualify your partitioning and ordering strategy. The <b><code>OVER<\/code><\/b> clause supports three subclauses, as shown in the following syntax:<\/p>\n<pre>&lt;window function&gt; OVER\n&#160; (\n&#160;&#160;&#160; [ PARTITION BY &lt;expression&gt; [, ... n] ]\n&#160;&#160;&#160; [ ORDER BY &lt;expression&gt; [ASC|DESC] [, ... n] ]\n&#160;&#160;&#160; [ ROWS|RANGE &lt;window frame&gt; ]\n&#160; )\n\n<\/pre>\n<p>The <b><code>PARTITION<\/code><\/b> <b><code>BY<\/code><\/b> subclause partitions the result set based on one or more columns or expressions. In most cases, you&#8217;ll probably use a single column. All window functions support the <b><code>PARTITION<\/code><\/b> <b><code>BY<\/code><\/b> subclause, but it is optional in each case. When the subclause is not specified, the entire result set is treated as a single partition.<\/p>\n<p>The <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause sorts one or more columns or expressions within the partition. The <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> clause applies strictly within the context of the partition. All ranking functions and most aggregate functions can use the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause. For ranking functions, the subclause is required. For aggregate functions, the subclause is optional. Only certain analytic functions can use the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause. However, those that can must use it.<\/p>\n<p><b>NOTE:<\/b> Most, but not all, aggregate functions support the <b><code>OVER<\/code><\/b> clause. If they support the <b><code>OVER<\/code><\/b> clause, then they support the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause. Unfortunately, Microsoft documentation is a bit inconsistent on which ones support the <b><code>OVER<\/code><\/b> clause and which do not. The easiest way to find out is to try them out, but know that the most common aggregate functions-such as <b><code>SUM<\/code><\/b>, <b><code>AVG<\/code><\/b>, <b><code>MIN<\/code><\/b>, <b><code>MAX<\/code><\/b>, and <b><code>COUNT<\/code><\/b>-do support the clause.<\/p>\n<p>The <b><code>ROWS\/RANGE<\/code><\/b> subclause further defines how the data is displayed within the partition. Ranking functions cannot use the <b><code>ROWS\/RANGE<\/code><\/b> subclause. Aggregate functions can use the subclause, but it is optional. Only two analytic functions-<b><code>FIRST_VALUE<\/code><\/b> and <b><code>LAST_VALUE<\/code><\/b>-can use the subclause, and it is optional for them as well. <\/p>\n<p>The <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause must be included if the <b><code>ROWS\/RANGE<\/code><\/b> subclause is specified. Also, if a window function supports the <b><code>ROWS\/RANGE<\/code><\/b> subclause but the subclause is not defined, the function behaves as if the subclause is specified at its default value, which affects the behavior of the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause. More on this later in the article.<\/p>\n<p>The details of how the subclauses fit together can seem a bit convoluted. The best way to understand how the various components work is to see them in action. The rest of the article uses examples to demonstrate these concepts. The examples are based on the table shown in the following T-SQL script:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">USE AdventureWorks2012;\nGO\n&#160;\nIF OBJECT_ID('RegionalSales', 'U') IS NOT NULL\nDROP TABLE RegionalSales;\nGO\n&#160;\nCREATE TABLE RegionalSales\n(\n&#160; SalesID INT NOT NULL IDENTITY PRIMARY KEY,\n&#160; SalesGroup NVARCHAR(30) NOT NULL,\n&#160; Country NVARCHAR(30) NOT NULL,\n&#160; AnnualSales INT NOT NULL\n);\nGO\n&#160;\nINSERT INTO RegionalSales \n&#160; (SalesGroup, Country, AnnualSales)\nVALUES\n&#160; ('North America', 'United States', 22000),\n&#160; ('North America', 'Canada', 32000),\n&#160; ('North America', 'Mexico', 28000),\n&#160; ('Europe', 'France', 19000),\n&#160; ('Europe', 'Germany', 22000),\n&#160; ('Europe', 'Italy', 18000),\n&#160; ('Europe', 'Greece', 16000),\n&#160; ('Europe', 'Spain', 16000),\n&#160; ('Europe', 'United Kingdom', 32000),\n&#160; ('Pacific', 'Australia', 18000),\n&#160; ('Pacific', 'China', 28000),\n&#160; ('Pacific', 'Singapore', 21000),\n&#160; ('Pacific', 'New Zealand', 18000),\n&#160; ('Pacific', 'Thailand', 17000),\n&#160; ('Pacific', 'Malaysia', 19000),\n&#160; ('Pacific', 'Japan', 22000);\nGO\n&#160;\n<\/pre>\n<p>The script creates a simple table and populates the table with sales data broken into sales groups and countries. As for what the sales represent, use your imagination. They can be anything from hamburgers to paper airplanes to relational database management systems.<\/p>\n<h1>Ranking Functions<\/h1>\n<p>Nothing has changed with the ranking functions in SQL Server 2012, and you might already be well versed in how they work. I&#8217;m including a brief overview here in order to be complete, but you can skip ahead if necessary, though you might find this section to be a handy refresher.<\/p>\n<p>The first example we&#8217;ll look at uses all four of the ranking functions to rank our sample sales data based on the amount of sales:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT\n&#160; SalesGroup,\n&#160; Country,\n&#160; AnnualSales,\n&#160; ROW_NUMBER() OVER(ORDER BY AnnualSales DESC) AS RowNumber,\n&#160; RANK() OVER(ORDER BY AnnualSales DESC) AS BasicRank,\n&#160; DENSE_RANK() OVER(ORDER BY AnnualSales DESC) AS DenseRank,\n&#160; NTILE(3) OVER(ORDER BY AnnualSales DESC) AS NTileRank\nFROM\n&#160; RegionalSales;\n&#160;\n<\/pre>\n<p>Notice that for each function, I include an <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause that sorts the <b><code>AnnualSales<\/code><\/b> column in descending order. Because I have not included a <b><code>PARTITION<\/code><\/b> <b><code>BY<\/code><\/b> subclause, the result set is treated as a single partition. Each ranking function ranks the data, based on the sorted <b><code>AnnualSales<\/code><\/b> values, in different ways. The following table shows the results returned by the <b><code>SELECT<\/code><\/b> statement.<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td class=\"style1\" valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>Country<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AnnualSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>RowNumber<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>BasicRank<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>DenseRank<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>NTileRank<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Canada<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United Kingdom<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Mexico<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>China<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United States<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Japan<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Germany<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Singapore<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>8<\/p>\n<\/td>\n<td valign=\"top\">\n<p>8<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Malaysia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>9<\/p>\n<\/td>\n<td valign=\"top\">\n<p>9<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>France<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>10<\/p>\n<\/td>\n<td valign=\"top\">\n<p>9<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Australia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>11<\/p>\n<\/td>\n<td valign=\"top\">\n<p>11<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Italy<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>12<\/p>\n<\/td>\n<td valign=\"top\">\n<p>11<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>New Zealand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>13<\/p>\n<\/td>\n<td valign=\"top\">\n<p>11<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Thailand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>14<\/p>\n<\/td>\n<td valign=\"top\">\n<p>14<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Greece<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>15<\/p>\n<\/td>\n<td valign=\"top\">\n<p>15<\/p>\n<\/td>\n<td valign=\"top\">\n<p>8<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Spain<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16<\/p>\n<\/td>\n<td valign=\"top\">\n<p>15<\/p>\n<\/td>\n<td valign=\"top\">\n<p>8<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;The <b><code>ROW_NUMBER<\/code><\/b> function simply numbers each row in the partition. Because the statement returns 16 rows and there is only one partition, the rows are numbered <b><code>1<\/code><\/b> through <b><code>16<\/code><\/b>. <\/p>\n<p>The <b><code>RANK<\/code><\/b> function also numbers each row consecutively, based on the sorted <b><code>AnnualSales<\/code><\/b> values, but also takes into account duplicate values by assigning those values the same rank and then skipping the rank value that would have been assigned to the second duplicate. For example, the first two rows are ranked <b><code>1<\/code><\/b>, so the third row is ranked <b><code>3<\/code><\/b> because the <b><code>2<\/code><\/b> has been skipped.<\/p>\n<p>The <b><code>DENSE_RANK<\/code><\/b> function takes a slightly different approach. It accounts for duplicates but doesn&#8217;t skip ranking values. Consequently, the first two rows receive a ranking value of <b><code>1<\/code><\/b>, as with <b><code>RANK<\/code><\/b>, but the third row receives a value of <b><code>2<\/code><\/b>.<\/p>\n<p>The <b><code>NTILE<\/code><\/b> function is a different animal all together. If you refer back to the <b><code>SELECT<\/code><\/b> statement, you&#8217;ll notice that I passed a value of <b><code>3<\/code><\/b> in as an argument to the function. As a result, the function divides the partition into three groups. That division is based on the total number of rows divided by the number specified in the function&#8217;s argument. In this case, the 16 rows in the result set are divided into one group of six rows and two groups of five rows. The function assigns a <b><code>1<\/code><\/b> to each row in the first group, a <b><code>2<\/code><\/b> to each row in the second group, and a <b><code>3<\/code><\/b> to each row in the third group.<\/p>\n<p>You might have also noticed in the example above that the result set is sorted based on the <b><code>AnnualSales<\/code><\/b> values (in descending order). However, that occurs only because we did not specify an <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> clause on the outer statement itself. As you&#8217;ll recall, the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause specified in the <b><code>OVER<\/code><\/b> clause is specific to the partition, so SQL Server defaults to a sort order based on the subclause. But the subclause is specific to the function associated with the <b><code>OVER<\/code><\/b> clause. That means, we can override the subclause&#8217;s sorting in the result set, without impacting the functions&#8217; results.<\/p>\n<p>Let&#8217;s look at an example to demonstrate what that looks like. The following <b><code>SELECT<\/code><\/b> statement is the same as the preceding one only now it includes an <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> clause that sorts first by the <b><code>SalesGroup<\/code><\/b> column and then by the <b><code>Country<\/code><\/b> column:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT\n&#160; SalesGroup,\n&#160; Country,\n&#160; AnnualSales,\n&#160; ROW_NUMBER() OVER(ORDER BY AnnualSales DESC) AS RowNumber,\n&#160; RANK() OVER(ORDER BY AnnualSales DESC) AS BasicRank,\n&#160; DENSE_RANK() OVER(ORDER BY AnnualSales DESC) AS DenseRank,\n&#160; NTILE(3) OVER(ORDER BY AnnualSales DESC) AS NTileRank\nFROM\n&#160; RegionalSales\nORDER BY\n&#160; SalesGroup, Country;\n&#160;\n<\/pre>\n<p>As you can see, nothing has changed but the addition of the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> clause. However, as the following table shows, the results in the ranking columns are in a different order:<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td class=\"style1\" valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>Country<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AnnualSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>RowNumber<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>BasicRank<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>DenseRank<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>NTileRank<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>France<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>10<\/p>\n<\/td>\n<td valign=\"top\">\n<p>9<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Germany<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Greece<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>15<\/p>\n<\/td>\n<td valign=\"top\">\n<p>15<\/p>\n<\/td>\n<td valign=\"top\">\n<p>8<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Italy<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>12<\/p>\n<\/td>\n<td valign=\"top\">\n<p>11<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Spain<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16<\/p>\n<\/td>\n<td valign=\"top\">\n<p>15<\/p>\n<\/td>\n<td valign=\"top\">\n<p>8<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United Kingdom<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Canada<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Mexico<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United States<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Australia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>11<\/p>\n<\/td>\n<td valign=\"top\">\n<p>11<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>China<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Japan<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Malaysia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>9<\/p>\n<\/td>\n<td valign=\"top\">\n<p>9<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>New Zealand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>13<\/p>\n<\/td>\n<td valign=\"top\">\n<p>11<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Singapore<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>8<\/p>\n<\/td>\n<td valign=\"top\">\n<p>8<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Thailand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>14<\/p>\n<\/td>\n<td valign=\"top\">\n<p>14<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The data in this result set is the same as the one in the preceding example. It&#8217;s just messier looking. For instance, the <b><code>RowNumber<\/code><\/b> value for France is <b><code>10<\/code><\/b>, the <b><code>BasicRank<\/code><\/b> value is <b><code>9<\/code><\/b>, the <b><code>DenseRank<\/code><\/b> value is <b><code>5<\/code><\/b>, and the <b><code>NTileRank<\/code><\/b> value is <b><code>2<\/code><\/b>, just as they were in the preceding example. However, because we specifically sorted our entire result set, the ranking columns themselves are no longer in order, but they still base their data on the sorted <b><code>AnnualSales<\/code><\/b> column, as defined in the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause of the <b><code>OVER<\/code><\/b> clause. What this points to is that the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause is specific to the window function associated with the <b><code>OVER<\/code><\/b> clause.<\/p>\n<p>Now let&#8217;s return to our original example, only this time we&#8217;ll add a <b><code>PARTITION<\/code><\/b> <b><code>BY<\/code><\/b> subclause to each rank:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT\n&#160; SalesGroup,\n&#160; Country,\n&#160; AnnualSales,\n&#160; ROW_NUMBER() OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS RowNumber,\n&#160; RANK() OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS BasicRank,\n&#160; DENSE_RANK() OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS DenseRank,\n&#160; NTILE(3) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS NTileRank\nFROM\n&#160; RegionalSales;\n&#160;\n<\/pre>\n<p>For each ranking function, we partition the results by the <b><code>SalesGroup<\/code><\/b> values, which breaks our result set into three distinct groups. The following table shows the results now returned by the <b><code>SELECT<\/code><\/b> statement:<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td class=\"style1\" valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>Country<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AnnualSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>RowNumber<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>BasicRank<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>DenseRank<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>NTileRank<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United Kingdom<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Germany<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>France<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Italy<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Greece<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Spain<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Canada<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Mexico<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United States<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>China<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Japan<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Singapore<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Malaysia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Australia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>New Zealand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Thailand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;As you can see, the ranking functions now each apply to the individual partitions, which are based on the sales group. For example, the Europe sales group includes six rows, one for each country. As a result, the <b><code>ROW_NUMBER<\/code><\/b> function ranks the rows <b><code>1<\/code><\/b> through <b><code>6<\/code><\/b>. &#160;However, because the last two values in that group are duplicates, the <b><code>RANK<\/code><\/b> and <b><code>DENSE_RANK<\/code><\/b> functions assign the first four rows <b><code>1<\/code><\/b> through <b><code>4<\/code><\/b> and assign a <b><code>5<\/code><\/b> to the last two rows. The <b><code>RANK<\/code><\/b> function doesn&#8217;t skip any numbers because the duplicates come at the end of the sorted <b><code>AnnualSales<\/code><\/b> column. And when the <b><code>NTILE<\/code><\/b> function breaks the Europe partition into three groups, each group contains only three rows.<\/p>\n<p>Now let&#8217;s see what happens if we add an <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> clause to the statement itself, as shown in the following example:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT\n&#160; SalesGroup,\n&#160; Country,\n&#160; AnnualSales,\n&#160; ROW_NUMBER() OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS RowNumber,\n&#160; RANK() OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS BasicRank,\n&#160; DENSE_RANK() OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS DenseRank,\n&#160; NTILE(3) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS NTileRank\nFROM\n&#160; RegionalSales\nORDER BY\n&#160; SalesGroup, Country;\n&#160;\n<\/pre>\n<p>Once again, I&#8217;ve sorted the result set first by <b><code>SalesGroup<\/code><\/b> and then by <b><code>Country<\/code><\/b>. As the following table demonstrates, the ranking values are now displayed in a different order:<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td class=\"style1\" valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>Country<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AnnualSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>RowNumber<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>BasicRank<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>DenseRank<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>NTileRank<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>France<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Germany<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Greece<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Italy<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Spain<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United Kingdom<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Canada<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Mexico<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United States<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Australia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>China<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Japan<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Malaysia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>New Zealand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>5<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Singapore<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Thailand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;Although the result set itself has been sorted, the ranking data is still based on the defined partition and sort order within the partition. Each country receives the same ranking values as they did in the earlier example, only now they&#8217;re in a different order.<\/p>\n<h1>Aggregate Functions<\/h1>\n<p>Aggregate functions work a bit differently from ranking functions, not only because of the functions themselves, but also in terms of how the subclauses work. For example, aggregate functions don&#8217;t require an <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause and can include a <b><code>ROWS\/RANGE<\/code><\/b> subclause. But first, let&#8217;s look at aggregate functions that use only the <b><code>PARTITION<\/code><\/b> <b><code>BY<\/code><\/b> subclause. In the following example, the <b><code>SELECT<\/code><\/b> statement uses several aggregate functions to calculate <b><code>AnnualSales<\/code><\/b> values for each partition:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT \n&#160; SalesGroup,\n&#160; Country,\n&#160; AnnualSales,\n&#160; COUNT(AnnualSales) OVER(PARTITION BY SalesGroup) AS CountryCount,\n&#160; SUM(AnnualSales) OVER(PARTITION BY SalesGroup) AS TotalSales,\n&#160; AVG(AnnualSales) OVER(PARTITION BY SalesGroup) AS AverageSales\nFROM\n&#160; RegionalSales\nORDER BY \n&#160; SalesGroup, AnnualSales DESC;\n&#160;\n<\/pre>\n<p>As before the statement partitions the data by sales group. In addition, for each function, I pass in the <b><code>AnnualSales<\/code><\/b> column as the argument because I want to perform my calculations on that column. The <b><code>SELECT<\/code><\/b> statement returns the results shown in the following table:<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p><b>Country<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p><b>AnnualSales<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p><b>CountryCount<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p><b>TotalSales<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p><b>AverageSales<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United Kingdom<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>123000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20500<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Germany<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>123000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20500<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>France<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>123000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20500<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Italy<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>123000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20500<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Greece<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>123000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20500<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Spain<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>123000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20500<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Canada<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>82000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>27333<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Mexico<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>82000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>27333<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United States<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>82000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>27333<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>China<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>143000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20428<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Japan<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>143000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20428<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Singapore<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>143000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20428<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Malaysia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>143000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20428<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Australia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>143000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20428<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>New Zealand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>143000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20428<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Thailand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>143000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20428<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Notice how the aggregate functions have been applied to each group. For example, the <b><code>COUNT<\/code><\/b> function returns a <b><code>6<\/code><\/b> for each row in the Europe group, the <b><code>SUM<\/code><\/b> function returns <b><code>123000<\/code><\/b> for each row in that group, and the <b><code>AVG<\/code><\/b> function returns <b><code>20500<\/code><\/b> for those rows.<\/p>\n<p>If you wanted to get at the aggregate calculations only, you can simplify your statement in order to eliminate duplicate values, as shown in the following example:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT DISTINCT\n&#160; SalesGroup,\n&#160; COUNT(AnnualSales) OVER(PARTITION BY SalesGroup) AS CountryCount,\n&#160; SUM(AnnualSales) OVER(PARTITION BY SalesGroup) AS TotalSales,\n&#160; AVG(AnnualSales) OVER(PARTITION BY SalesGroup) AS AverageSales\nFROM\n&#160; RegionalSales\nORDER BY \n&#160; TotalSales DESC;\n&#160;\n<\/pre>\n<p>Now the <b><code>SELECT<\/code><\/b> statement returns only the data we need:<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td class=\"style1\" valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>CountryCount<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>TotalSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AverageSales<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>143000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20428<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>123000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20500<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>82000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>27333<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;So far, everything we&#8217;ve looked at to this point has existed in SQL Server since the 2005 release. However, SQL Server 2012 now supports the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause for aggregate functions. For example, the following <b><code>SELECT<\/code><\/b> statement adds an <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause that sorts <b><code>AnnualSales<\/code><\/b> in descending order:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT \n&#160; SalesGroup,\n&#160; Country,\n&#160; AnnualSales,\n&#160; COUNT(AnnualSales) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS CountryCount,\n&#160; SUM(AnnualSales) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS TotalSales,\n&#160; AVG(AnnualSales) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS AverageSales\nFROM\n&#160; RegionalSales;\n&#160;\n<\/pre>\n<p>The data is still partitioned by the <b><code>SalesGroup<\/code><\/b> column, only now we&#8217;ve added the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause. However, as the following table shows, the statement&#8217;s results might not be quite what you expect:<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td class=\"style1\" valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>Country<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AnnualSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>CountryCount<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>TotalSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AverageSales<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United Kingdom<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Germany<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>54000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>27000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>France<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>73000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>24333<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Italy<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>91000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22750<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Greece<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>123000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20500<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Spain<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>123000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20500<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Canada<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Mexico<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>60000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>30000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United States<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>82000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>27333<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>China<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Japan<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>50000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>25000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Singapore<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>71000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>23666<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Malaysia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>4<\/p>\n<\/td>\n<td valign=\"top\">\n<p>90000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22500<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Australia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>126000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>New Zealand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>6<\/p>\n<\/td>\n<td valign=\"top\">\n<p>126000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Thailand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>7<\/p>\n<\/td>\n<td valign=\"top\">\n<p>143000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20428<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;In fact, when you use the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause with an aggregate function, the aggregated data changes with each row. The result set now shows moving averages and cumulative totals. For example, Germany shows a count of <b><code>2<\/code><\/b>, a total of <b><code>54000<\/code><\/b>, and an average of <b><code>27000<\/code><\/b>. Because Germany is the second row in the partition, as determined by the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause, the aggregated totals reflect only those two rows. The same thing goes for France. Because it comes in at number <b><code>3<\/code><\/b>, the aggregated totals reflect only the first three rows. To complicate matters, duplicated rows are grouped together, as is the case with Greece and Spain.<\/p>\n<p>There&#8217;s a reason for this behavior. As you&#8217;ll recall from earlier in the article, when a window function supports the <b><code>ROWS\/RANGE<\/code><\/b> subclause but the subclause has not been specified, the function operates as if it has been specified with its default value. And that default setting impacts the <b><code>ORDER<\/code><\/b> <b><code>BY <\/code><\/b>subclause. <\/p>\n<p>The default setting for the <b><code>ROWS\/RANGE<\/code><\/b> subclause is <b><code>RANGE<\/code><\/b> <b><code>BETWEEN<\/code><\/b> <b><code>UNBOUNDED<\/code><\/b> <b><code>PRECEDING<\/code><\/b> <b><code>AND<\/code><\/b> <b><code>CURRENT<\/code><\/b> <b><code>ROW<\/code><\/b>. This means that, for each row in the partition, the window function is applied to the current row and the preceding rows only. So aggregations don&#8217;t operate on the entire set of values within the partition, but only on the value in the current row and the previous rows, as we saw in the example above.<\/p>\n<p><b>NOTE:<\/b> The main difference between a <b><code>ROWS<\/code><\/b> clause and a <b><code>RANGE<\/code><\/b> clause is in the way duplicate data is treated. <b><code>ROWS<\/code><\/b> treats duplicates as distinct values. <b><code>RANGE<\/code><\/b> treats them as a single entity, as the above result set indicates.<\/p>\n<p>The way to get around the default behavior, of course, is to add a <b><code>ROWS\/RANGE<\/code><\/b> subclause that overrides that behavior, as shown in the following example:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT \n&#160; SalesGroup,\n&#160; Country,\n&#160; AnnualSales,\n&#160; COUNT(AnnualSales) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC \n&#160;&#160;&#160;&#160;&#160; ROWS 2 PRECEDING) AS CountryCount,\n&#160; SUM(AnnualSales) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC \n&#160;&#160;&#160;&#160;&#160; ROWS 2 PRECEDING) AS TotalSales,\n&#160; AVG(AnnualSales) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC \n&#160;&#160;&#160;&#160;&#160; ROWS 2 PRECEDING) AS AverageSales\nFROM\n&#160; RegionalSales;\n&#160;\n<\/pre>\n<p>Notice that I&#8217;ve added the subclause <b><code>ROWS<\/code><\/b> <b><code>2<\/code><\/b> <b><code>PRECEDING<\/code><\/b> to each instance of the <b><code>OVER<\/code><\/b> clause. Now for each partition, the aggregate function applies only to the current row and the two preceding rows, as shown in the following results:<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td class=\"style1\" valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>Country<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AnnualSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>CountryCount<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>TotalSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AverageSales<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United Kingdom<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Germany<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>54000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>27000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>France<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>73000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>24333<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Italy<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>59000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19666<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Greece<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>53000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17666<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Spain<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>50000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16666<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Canada<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Mexico<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>60000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>30000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United States<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>82000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>27333<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>China<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>1<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Japan<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>2<\/p>\n<\/td>\n<td valign=\"top\">\n<p>50000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>25000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Singapore<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>71000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>23666<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Malaysia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>62000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>20666<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Australia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>58000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19333<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>New Zealand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>55000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18333<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Thailand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>3<\/p>\n<\/td>\n<td valign=\"top\">\n<p>53000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17666<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;Because the <b><code>ROWS<\/code><\/b> subclause is included, each aggregated value never calculates more than three rows, so the <b><code>CountryCount<\/code><\/b> value will never exceed <b><code>3<\/code><\/b> and the total and average sales will never represent the total amounts within the group, unless that group has fewer than four rows. If you don&#8217;t want to aggregate your partitioned data in this way-with totals and averages that don&#8217;t reflect the entire partition-your best bet is to go with the <b><code>PARTITION<\/code><\/b> <b><code>BY<\/code><\/b> subclause only and not the other subclauses.<\/p>\n<h1>Analytic Functions<\/h1>\n<p>Analytic functions work much the same way as aggregate functions, except that the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause is required for those functions that support the clause. In our next example, we&#8217;ll try out the <b><code>FIRST_VALUE<\/code><\/b> and <b><code>LAST_VALUE<\/code><\/b> analytic functions. The <b><code>FIRST_VALUE<\/code><\/b> function retrieves the first value from a sorted list, and the <b><code>LAST_VALUE<\/code><\/b> function retrieves the last value. In the following example, the <b><code>SELECT<\/code><\/b> statement uses both of these functions to calculate <b><code>AnnualSales<\/code><\/b> values in each sales group:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT \n&#160; SalesGroup,\n&#160; Country,\n&#160; AnnualSales,\n&#160; FIRST_VALUE(AnnualSales) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS HighestSales,\n&#160; LAST_VALUE(AnnualSales) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS LowestSales\nFROM\n&#160; RegionalSales;\n&#160;\n<\/pre>\n<p>Once again, I use the <b><code>PARTITION<\/code><\/b> <b><code>BY<\/code><\/b> subclause to partition the result set by sales group. In addition, I use the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> subclause to specify that the <b><code>AnnualSales<\/code><\/b> values be sorted in descending order. The following table shows the results returned by the <b><code>SELECT<\/code><\/b> statement.<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td class=\"style1\" valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>Country<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AnnualSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>HighestSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>LowestSales<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United Kingdom<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Germany<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>France<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Italy<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Greece<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Spain<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Canada<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Mexico<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United States<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>China<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Japan<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Singapore<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Malaysia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Australia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>New Zealand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Thailand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;As to be expected, the result set is grouped by the <b><code>SalesGroup<\/code><\/b> column, with the <b><code>AnnualSales<\/code><\/b> values in each group sorted. The <b><code>HighestSales<\/code><\/b> column displays the first of the sorted values, and the <b><code>LowestSales<\/code><\/b> column displays the last of the sorted values. But these values are running totals because the <b><code>FIRST_VALUE<\/code><\/b> and <b><code>LAST_VALUE<\/code><\/b> functions support the <b><code>ROWS\/RANGE<\/code><\/b> subclause, which impacts the <b><code>ORDER<\/code><\/b> <b><code>BY<\/code><\/b> operation. For example, the highest amount of sales for the France row is <b><code>32000<\/code><\/b> and the lowest amount is <b><code>19000<\/code><\/b>. These calculations are based only on the first three rows in this partition as a result of the <b><code>ROWS\/RANGE<\/code><\/b> default settings being applied.<\/p>\n<p>As before, we can override the subclause&#8217;s default behavior. Only this time, let&#8217;s change it to incorporate all <b><code>AnnualSales<\/code><\/b> in each calculation, regardless of row:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT \n&#160; SalesGroup,\n&#160; Country,\n&#160; AnnualSales,\n&#160; FIRST_VALUE(AnnualSales) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS HighestSales,\n&#160; LAST_VALUE(AnnualSales) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC\n&#160;&#160;&#160;&#160;&#160; ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) \n&#160;&#160;&#160;&#160;&#160; AS LowestSales\nFROM\n&#160; RegionalSales;\n&#160;\n<\/pre>\n<p>Notice that our <b><code>ROWS<\/code><\/b> clause specifies unbounded preceding and following values, which means all values should be included in the calculations. The following table shows what the results look like:<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td class=\"style1\" valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>Country<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AnnualSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>HighestSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>LowestSales<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United Kingdom<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Germany<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>France<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Italy<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Greece<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Spain<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Canada<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Mexico<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United States<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>China<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Japan<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Singapore<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Malaysia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Australia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>New Zealand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Thailand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;As you can see, the <b><code>HighestSales<\/code><\/b> and <b><code>LowestSales<\/code><\/b> columns now display duplicate values for each row in a sales group, providing both the first and last value, respectively, in the sorted <b><code>AnnualSales<\/code><\/b> column. You can, of course, simplify your <b><code>SELECT<\/code><\/b> statement to retrieve only the necessary distinct values, as we did in an earlier example.<\/p>\n<p>Now let&#8217;s look at two other analytic functions: <b><code>LAG<\/code><\/b> and <b><code>LEAD<\/code><\/b>. The <b><code>LEAD<\/code><\/b> function retrieves a value from a row previous to the current one. The <b><code>LAG<\/code><\/b> function retrieves a value from a row after the current one. The following <b><code>SELECT<\/code><\/b> statement demonstrates how to use these functions:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT \n&#160; SalesGroup,\n&#160; Country,\n&#160; AnnualSales,\n&#160; LAG(AnnualSales, 1) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS PreviousSale,\n&#160; LEAD(AnnualSales, 1) OVER(PARTITION BY SalesGroup\n&#160;&#160;&#160; ORDER BY AnnualSales DESC) AS NextSale\nFROM\n&#160; RegionalSales;\n&#160;\n<\/pre>\n<p>First, notice that we pass a second argument into the functions, in this case, <b><code>1<\/code><\/b>. The argument indicates that we go one row up or down to retrieve the value from the sorted <b><code>AnnualSales<\/code><\/b> values. The following table shows the results returned by the <b><code>SELECT<\/code><\/b> statement.<\/p>\n<table class=\"MsoTableGrid\">\n<tbody>\n<tr>\n<td class=\"style1\" valign=\"top\">\n<p><b>SalesGroup<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>Country<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>AnnualSales<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>PreviousSale<\/b><\/p>\n<\/td>\n<td class=\"style1\" valign=\"top\">\n<p><b>NextSale<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United Kingdom<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>NULL<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Germany<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>France<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Italy<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Greece<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Europe<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Spain<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>16000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>NULL<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Canada<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>NULL<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Mexico<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>32000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>North America<\/p>\n<\/td>\n<td valign=\"top\">\n<p>United States<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>NULL<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>China<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>NULL<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Japan<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>28000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Singapore<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>22000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Malaysia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>21000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Australia<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>19000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>New Zealand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p>Pacific<\/p>\n<\/td>\n<td valign=\"top\">\n<p>Thailand<\/p>\n<\/td>\n<td valign=\"top\">\n<p>17000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>18000<\/p>\n<\/td>\n<td valign=\"top\">\n<p>NULL<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&#160;As the results show, each row displays <b><code>AnnualSales<\/code><\/b> values from the previous and next rows within each partition, unless it&#8217;s a first or last row, in which case <b><code>NULL<\/code><\/b> is returned. For example, the United Kingdom row returns a <b><code>NULL<\/code><\/b> in the <b><code>PreviousSale<\/code><\/b> column because no rows precede this row. However, the <b><code>NextSale<\/code><\/b> column displays the amount <b><code>22000<\/code><\/b>, the <b><code>AnnualSales<\/code><\/b> amount from the row that follows.<\/p>\n<p>SQL Server supports four other analytic functions that mostly have to do with calculating percentages. It also supports additional ways to configure the <b><code>ROWS\/RANGE<\/code><\/b> subclause. In fact, the subclause supports a number of variations. But the key to understanding the subclause is to become familiar with the <b><code>OVER<\/code><\/b> clause and how the subclauses work together to partition and present data. For a complete discussion of the clause, see the topic &#8220;<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms189461.aspx\">OVER Clause (Transact-SQL)<\/a>&#8221; in SQL Server Books Online. And be willing to try out window functions in different scenarios. They&#8217;re the type of feature you need to mess with for a while before you become fully comfortable with using them.&#160;<\/p>\n<p><\/p>\n<div><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>For some time, Microsoft had a few window functions, but not the full set specified in the SQL 2003 standard. Now, in SQL Server 2012 we have the whole range, and extremely useful they are too. There&#8217;s no longer an excuse to avoid them, particularly now you have Rob&#8217;s gentle introduction.&hellip;<\/p>\n","protected":false},"author":221841,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143531],"tags":[4242,4150,4151,4252],"coauthors":[],"class_list":["post-1598","post","type-post","status-publish","format-standard","hentry","category-t-sql-programming-sql-server","tag-basics","tag-sql","tag-sql-server","tag-t-sql-programming"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1598","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221841"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1598"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1598\/revisions"}],"predecessor-version":[{"id":92532,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1598\/revisions\/92532"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1598"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1598"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1598"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1598"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}