Ranking Records Over Partitions
Ranking Records Over Partitions
Ranking the Records
Introduction
Consider the following SQL statement:
USE LambdaPropertiesManagement1; GO SELECT props.Bedrooms, props.MonthlyRate FROM Listing.Properties props ORDER BY props.MonthlyRate; GO
This produces:
The goal of the above statement was to produce the list of properties arranged by the monthly rate from the least expensive up. What is missing is a column that clearly shows such a ranking as 1 (for the first group), 2 (for the second group), and so on. As another example, if we have groups of records, we may want to know from one record starts a cetain category and where that category ends. Transact-SQL provides functions that can be used to rank records. Those functions can be combined with other functions, such as aggregates, to get more statistics. The functions used to rank groups of records are call ranking functions.
Practical Learning: Introducing Record Ranking |
USE LambdaPropertiesManagement1; GO SELECT props.Bedrooms, props.MonthlyRate FROM Listing.Properties props ORDER BY props.MonthlyRate; GO
If you have a list of records and you make a selection from it. The records would appear in the same order they were created. Sometimes, when the records display, if they were not created with an identity column or a sequence, you may want a column that shows the incremental sequence of the records. Transact-SQL is equipped with a function named ROW_NUMBER that displays the records, each with an integer that shows its ordered position. The syntax of the ROW_NUMBER() function is: |
ROW_NUMBER() OVER([PARTITION BY value_expression, ... [ n ] ] order_by_clause) RETURNS bigint
The ROW_NUMBER() function takes no argument. It is followed by a call to OVER(). If you call the parameter-less OVER(), the incrementing numbers of the records would be displayed. If you want to display records in groups, create a partition passed to OVER(). In this case, the incrementing numbers of each group would display.
Practical Learning: Showing the Row Number of Each Record in Each Group |
USE LambdaPropertiesManagement1; GO SELECT props.PropertyType Type, props.MonthlyRate Rate, ROW_NUMBER() OVER(ORDER BY props.PropertyType) Rank FROM Listing.Properties props; GO
USE LambdaPropertiesManagement1;
GO
SELECT props.PropertyType Type,
props.MonthlyRate Rate,
ROW_NUMBER() OVER(PARTITION BY props.PropertyType ORDER BY props.PropertyType) Rank
FROM Listing.Properties props;
GO
USE LambdaPropertiesManagement1;
GO
SELECT props.PropertyType Type,
props.MonthlyRate Rate,
props.City,
ROW_NUMBER() OVER(PARTITION BY props.City ORDER BY props.PropertyType) [Row #]
FROM Listing.Properties props;
GO
Ranking the Records Over |
If you have a column with repeating values, you can get a list of the repeating values and rank them as 1 for the first category, 2 for the second, and so on. To support this, Transact-SQL provides a ranking function named RANK. Its syntax is:
RANK() OVER([partition_by_clause] order_by_clause) RETURNS bigint;
This function takes no argument. It is followed by calling OVER(). The RANK() function is used to show from what record to what record a (or each) group starts. If the order of records is messy, the function cannot perform its function. After all, imagine you have a list of properties as Apartment, Townhouse, Apartment, Single Family, Single Family, Townhouse, Apartment, Single Family. |
There is no way you can determine where a group starts and where it ends. For this reason, the RANK() function requires that the records be arranged, which is done by adding an ORDER BY clause. The arrangement is passed to OVER().
Before arranging the records, you can ask the database engine to create partitions. Although you can use any column of your choice, you should use a column that is in the SELECT statement.
Practical Learning: Ranking the Records Over |
USE LambdaPropertiesManagement1; GO SELECT PropertyType [Property Type], RANK() OVER(ORDER BY PropertyType) [Ranking by Type] FROM Listing.Properties; GO
USE LambdaPropertiesManagement1;
GO
SELECT props.PropertyType Type,
props.MonthlyRate Rate,
RANK() OVER(ORDER BY PropertyType) [Ranking by Type],
ROW_NUMBER() OVER(PARTITION BY props.PropertyType ORDER BY props.PropertyType) Rank
FROM Listing.Properties props;
GO
SELECT DISTINCT(PropertyType) [Property Type], RANK() OVER(ORDER BY PropertyType) [Ranking by Type] FROM Listing.Properties; GO
USE LambdaPropertiesManagement1; GO SELECT props.PropertyType "Property Type", props.MonthlyRate Rate, RANK() OVER(ORDER BY props.MonthlyRate) "Ranking" FROM Listing.Properties props; GO
USE LambdaPropertiesManagement1;
GO
SELECT props.PropertyType,
props.MonthlyRate Rate,
RANK() OVER(PARTITION BY props.PropertyType ORDER BY props.MonthlyRate) Ranking
FROM Listing.Properties props;
GO
USE LambdaPropertiesManagement1; GO SELECT pmts.RegistrationNumber [Regist #], pmts.AmountPaid Amount, RANK() OVER(ORDER BY pmts.AmountPaid) Ranking FROM Rentals.Payments pmts; GO
USE LambdaPropertiesManagement1; GO SELECT regs.TenantCode [Account #], pmts.AmountPaid Amount, RANK() OVER(ORDER BY pmts.AmountPaid) Ranking FROM Rentals.Payments pmts INNER JOIN Rentals.Registrations regs ON pmts.RegistrationNumber = regs.RegistrationNumber; GO
USE LambdaPropertiesManagement1; GO SELECT DISTINCT(CONCAT(N'Tenant: ', tens.LastName, N' - ', tens.FirstName, N', Property #', props.PropertyNumber, N': ', props.PropertyType)) [Registration Information], pmts.AmountPaid [Amount Paid], RANK() OVER(ORDER BY pmts.AmountPaid) Ranking FROM Rentals.Payments pmts INNER JOIN Rentals.Registrations regs ON pmts.RegistrationNumber = regs.RegistrationNumber INNER JOIN Rentals.Tenants tens ON tens.TenantCode = regs.TenantCode INNER JOIN Listing.Properties props ON regs.PropertyNumber = props.PropertyNumber ORDER BY Ranking; GO
Densely Ranking Records
When creating groups of records, probably the most basic piece of information you may want to get is what group comes first, followed by which one, and so on. To let you get this information, Transact-SQL provides a function named DENSE_RANK. Its syntax is:
DENSE_RANK() OVER([partition_by_clause] order_by_clause) RETURNS bigint
Like RANK(), this function takes 0 argument and its OVER() clause requires that the records be arranged.
Practical Learning: Ranking the Records Over |
SELECT PropertyType [Property Type], DENSE_RANK() OVER(ORDER BY PropertyType) [Ranking by Type] FROM Listing.Properties; GO
USE LambdaPropertiesManagement1; GO SELECT DISTINCT(PropertyType) [Property Type], DANSE_RANK() OVER(ORDER BY PropertyType) [Ranking by Type] FROM Listing.Properties; GO
USE LambdaPropertiesManagement1; GO SELECT props.PropertyType [Property Type], props.MonthlyRate Rate, DENSE_RANK() OVER(ORDER BY props.MonthlyRate) Ranking FROM Listing.Properties props; GO
USE LambdaPropertiesManagement1; GO SELECT pmts.PaymentReason Category, pmts.AmountPaid Amount, DENSE_RANK() OVER(ORDER BY pmts.AmountPaid) Ranking FROM Rentals.Payments pmts; GO
USE LambdaPropertiesManagement1;
GO
SELECT pmts.PaymentReason Category,
pmts.AmountPaid Amount,
DENSE_RANK() OVER(ORDER BY pmts.AmountPaid) Ranking
FROM Rentals.Payments pmts
WHERE pmts.PaymentReason = N'Monthly Payment';
GO
USE LambdaPropertiesManagement1;
GO
SELECT pmts.RegistrationNumber [Regist #],
pmts.AmountPaid Amount,
DENSE_RANK() OVER(ORDER BY pmts.AmountPaid) Ranking
FROM Rentals.Payments pmts
WHERE pmts.PaymentReason = N'Monthly Payment';
GO
USE LambdaPropertiesManagement1;
GO
SELECT pmts.RegistrationNumber [Regist #],
pmts.AmountPaid Amount,
DENSE_RANK() OVER(PARTITION BY pmts.RegistrationNumber ORDER BY pmts.AmountPaid) Ranking
FROM Rentals.Payments pmts
WHERE pmts.PaymentReason = N'Monthly Payment';
GO
SELECT DISTINCT(pmts.RegistrationNumber) [Regist #], pmts.AmountPaid Amount, DENSE_RANK() OVER(PARTITION BY pmts.RegistrationNumber ORDER BY pmts.AmountPaid) Ranking FROM Rentals.Payments pmts WHERE pmts.PaymentReason = N'Monthly Payment'; GO
Notice that sometimes different registrations have the same monthly payment (when the monthly rates of different properties are the same) or sometimes the same registration has different payments (when the monthly rate has increased for the same apartment)
So far, we were letting the database engine figure out how many groups would be created based on the repeating values of a certain column. Tiling consists of creating a number of groups of records. This means that you must indicate the number of groups you want. This time, it doesn't matter whether you choose a column that has repeating values. You simply create groups of records the way you want. To assist you with this, Transact-SQL provides the NTILE() function. Its syntax is:
NTILE (integer_expression) OVER( [ <partition_by_clause> ] < order_by_clause > ) RETURNS bigint
The NTILE() function takes one argument as an integer. That number must be positive. The number should be less than the total number of records. If you specify:
|
You must call the NTILE() function followed by a call to OVER(), which must have at least an arangement of records. Additionnally, you can specify a partitioning of records. If you do this, the database engine would create the number of groups based on the value passed to the NTILE() function, then each partition would have its own tiling scheme.
Practical Learning: Ranking the Records Over |
1> SELECT tens.TenantCode [Account #], 2> tens.FirstName [First Name], 3> tens.LastName [Last Name], 4> tens.MaritalStatus [Status], 5> NTILE(20) OVER(ORDER BY tens.TenantCode) Tiles 6> FROM Rentals.Tenants tens; 7> GO Account # First Name Last Name Status Tiles ---------- -------------- ------------ ---------------- --------- 204059 Reyza Haffaz NULL 1 292470 James Thomason Single 2 292475 James Thomason Married 3 293750 Diana Woodson NULL 4 293759 Michael Tiernan Single 5 295800 David Weaks Married 6 295804 Mahty Shaoul Married 7 385974 Elise Provoski Separated 8 495294 Tracy Warrens Divorced 9 524790 Christopher Shermann Married 10 524794 Nancy Shermann Single 11 624050 Frank Ulm Single 12 824850 Grace Flores Married 13 824857 Grace Curryan Married 14 839405 Phillippe Anderson Single 15 927407 Ann Sanders Married 16 (16 rows affected) 1>
SELECT tens.TenantCode [Account #],
tens.FirstName [First Name],
tens.LastName [Last Name],
tens.MaritalStatus [Status],
NTILE(6) OVER(ORDER BY tens.TenantCode) Tiles
FROM Rentals.Tenants tens;
GO
USE LambdaPropertiesManagement1;
GO
SELECT tens.TenantCode [Account #],
tens.FirstName [First Name],
tens.LastName [Last Name],
tens.MaritalStatus [Status],
NTILE(4) OVER(ORDER BY tens.TenantCode) Tiles
FROM Rentals.Tenants tens;
GO
USE LambdaPropertiesManagement1;
GO
SELECT tens.TenantCode [Account #],
tens.FirstName [First Name],
tens.LastName [Last Name],
tens.MaritalStatus [Status],
NTILE(4) OVER(PARTITION BY tens.MaritalStatus ORDER BY tens.TenantCode) Tiles
FROM Rentals.Tenants tens;
GO
|
||
Previous | Copyright © 2012-2022, FunctionX | Next |
|