## Introduction to SQL Server Window Functions

Have you ever found yourself stuck in a situation where you need to do an aggregate operation while still maintaining the detail-level value? That’s where window functions come in handy.

In this article, we’ll dive into the definition and examples of window functions, Microsoft’s improvements to them, and the OVER() clause’s function in window functions.

## Definition and Examples of Window Functions

Window functions, also referred to as analytic functions, are a type of SQL function that performs a calculation across an ordered set of rows in a table, referred to as a window, and returns a single result for each row. They are particularly useful when you want to perform aggregate operations while maintaining detail-level values.

To better understand window functions, let’s consider a simple example. Suppose we have a table called “Employees” with various columns such as “Name,” “Salary,” and “Department.” We want to calculate the average salary for each department and return a list of employees with their respective salaries and the average salary for that department.

A common approach to obtain this result would be to use GROUP BY and aggregate functions such as SUM and AVG. However, this approach does not provide us with the detail-level values.

We’ll only get the aggregated values per department. That’s where window functions come in handy.

By using window functions like AVG OVER(PARTITION BY Department), we can calculate the average salary for each department while still maintaining the detail-level values of each employee’s salary. This means we get the aggregated value, the average salary for the department, alongside the detail level value, the employee’s salary.

### Microsoft’s Improvements to Window Functions

Microsoft has improved window functions for SQL Server by introducing ranking functions and analytic functions. Ranking functions allow you to calculate a rank for each row based on a specified criteria, while analytic functions allow you to perform running totals, averages, or other calculations over a set of rows.

For example, the rank() function can be used to return the rank of each salesperson based on their sales amount, helping you sort the data for better understanding. The running total calculation, on the other hand, can help you keep track of your finances, and determine your spending pattern by summing up your expenses over a specified period.

### The OVER() Clause and Its Function in Window Functions

The OVER() clause is a fundamental piece of window functions. This clause allows you to specify a user-specified range or window within which to perform a calculation.

It behaves as an aggregate function to define the calculation scope for the window function. The OVER () clause works by using a base query and performing the calculation on a portion of the data within a specified range.

The range can be selected to fit your needs, depending on the level of detail you require. The range could be a partition, which divides the data into groups and performs the calculation on each group independently.

### Getting OVER() Window Functions

Let’s take a deeper dive into the applications of the OVER() clause in window functions.

### Comparison of GROUP BY and OVER() in Aggregations

When performing aggregations, we are usually limited to using GROUP BY clauses to aggregate the non-aggregate fields and SUM, AVG, MAX, and MIN functions to do the calculations. The problem is, we lose detail-level data because the GROUP BY function aggregates all the rows with the same value in a particular field.

The OVER() clause, on the other hand, ensures that we do not lose any information by returning detailed information alongside aggregated data. By using the OVER() clause, we can obtain aggregated information at a particular logical level of our data simultaneously.

### Example Data and Table Used Throughout Subsequent Examples

Throughout the rest of the article, we’ll be using the following data and table for illustration purposes. We have the “WindowTable,” which contains details of “House,” “FullName,” “PhysicalSkill,” and “MentalSkill.”

### Using OVER() to Maintain Detail Levels While Returning Summed Values

Suppose we want to find the total Physical Skill points for each House, alongside the Total Physical Skill points across all the Houses. We can combine the PARTITION BY and the SUM functions in the OVER() clause to achieve this.

```
SELECT House, FullName, PhysicalSkill,
SUM(PhysicalSkill) OVER (PARTITION BY House) AS TotalPhysicalSkillHouse,
SUM(PhysicalSkill) OVER () AS TotalPhysicalSkillAllHouses
FROM WindowTable
```

By grouping the Physical Skills by the House, we get the total Physical Skill points across all the Houses, as shown in the “TotalPhysicalSkillAllHouses” column.

### Narrowing Down the Window Using ROWS or RANGE

Sometimes we want to get running totals, averages, or other calculations over a set of rows, but we don’t need to include all the rows in the aggregation. We can use the ROWS or RANGE keywords in the OVER() clause to narrow down our scope of calculation.

For example, we can use ROWS BETWEEN CURRENT ROW AND UNBOUNDED PRECEDING to obtain a running total, i.e., the sum of the Physical Skill scores within the partition, up to the current row in the partition.

```
SELECT House, FullName, PhysicalSkill,
SUM(PhysicalSkill) OVER (PARTITION BY House
ORDER BY FullName ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
AS RunningTotalPhysical
FROM WindowTable
```

### Illustrating the Difference Between ROWS and RANGE Using Examples

Let’s consider an example of calculating running totals for the “House” column to illustrate the difference between ROWS and RANGE as follows:

```
SELECT House, FullName, PhysicalSkill,
SUM(PhysicalSkill) OVER (PARTITION BY House
ORDER BY FullName RANGE BETWEEN CURRENT ROW AND 1 FOLLOWING)
AS RunningTotalPhysical,
SUM(PhysicalSkill) OVER (PARTITION BY House
ORDER BY FullName ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING)
AS RunningTotalPhysical2
FROM WindowTable
```

In this example, we’ve used both ROWS and RANGE to calculate running totals. The RANGE-Based Running Total performs the sum of only one row, unlike the ROWS-Based Running Total, which sums up all rows up to and including the current row.

## Conclusion:

We hope that this article has given you a better understanding of SQL Server Window Functions, the OVER() clause’s function in window functions, ranking functions, analytic functions, and their application in various scenarios. Use this knowledge to enhance your ability to organize data, obtain the desired result and take full advantage of SQL server capabilities.

In summary, SQL Server Window Functions provide a powerful tool for performing aggregate operations while maintaining detail-level values. Microsoft has improved window functions with the introduction of ranking functions and analytic functions.

The OVER() clause is a fundamental piece of window functions, allowing you to specify a user-specified range or window within which to perform a calculation. By using the OVER() clause, you can obtain aggregated information at a particular logical level of your data simultaneously.

You can also use ROWS or RANGE keywords in the OVER() clause to narrow down the scope of calculations. Understanding SQL Server Window Functions is important to organize data, obtain the desired result, and take full advantage of SQL server capabilities, making it a valuable tool for data analysts and developers alike.