What is window function: Imagine you have a dataset with many rows, and you want to perform some calculations on each row based on a group of rows related to it. This group of rows is called a "window" or "frame."
In the context of databases and data analysis, a window function, also known as an analytic function or windowed function, is a type of function that performs a calculation across a set of rows related to the current row within a partition of a result set. This set of rows is called a "window" or "frame."
Window aggregate functions in SQL allow you to perform aggregate calculations across a "window" of rows related to the current row in your result set. These functions are commonly used in analytical and reporting queries to calculate running totals, moving averages, rankings, and other calculations that involve data from multiple rows.
The basic syntax for using window aggregate functions is as follows:
<Window Function> (<expression>) OVER (
[PARTITION BY <partition_column(s)>]
ORDER BY <order_column(s)>
[ROWS <frame_specification>]
)
Calculate a Running Total
SELECT
custid,
orderid,
val,
SUM(val) OVER(PARTITION BY custid) AS custtotal,
SUM(val) OVER() AS grandtotal
FROM Sales.OrderValues

suppose that you wanted to query the Sales.OrderValues view and compute the running total values from the beginning of the current customer’s activity until the current order. You need to use the SUM aggregate.
SELECT custid, orderid, orderdate, val,
SUM(val) OVER(PARTITION BY custid
ORDER BY orderdate, orderid ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS runningtotal
FROM Sales.OrderValues
--OR----
SELECT custid, orderid, orderdate, val,
SUM(val) OVER(PARTITION BY custid ORDER BY orderdate, orderid) AS runningtotal
FROM Sales.OrderValues

As another example for a window frame extent, if you wanted the frame to include only the last three rows, you would use the form ROWS BETWEEN 2 PRECEDING AND CURRENT ROW.
SELECT custid, orderid, orderdate, val,
SUM(val) OVER(PARTITION BY custid
ORDER BY orderdate, orderid ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS runningtotal
FROM Sales.OrderValues

ROWS BETWEEN 2 PRECEDING AND CURRENT ROW: This part specifies the window frame for the running total calculation. It instructs the SQL engine to consider the current row and the two preceding rows in the ordering specified (orderdate, orderid) within each partition. So, for each row in the result set, the running total will include the values of the current row and the two rows that come before it according to the specified ordering.
ROWS vs. RANGE
In SQL Server 2012, the ROWS option usually gets optimized much better than RANGE when using the same delimiters. If you define a window with a window order clause but without a window frame clause, the default is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. Therefore, unless you are after the special behavior you get from RANGE that includes peers, make sure you explicitly use the ROWS option
Window Ranking Functions
WITH CTE AS (
SELECT TOP 10 custid, orderid, val,
ROW_NUMBER() OVER(ORDER BY val) AS rownum,
RANK() OVER(ORDER BY val) AS rnk,
DENSE_RANK() OVER(ORDER BY val) AS densernk
FROM Sales.OrderValues
)
SELECT *,
NTILE(5) OVER(ORDER BY val) AS ntile5,
--arrange the 10 rows within the 5 partition 10/5 = 2 (2 rows in each partition)
NTILE(6) OVER(ORDER BY val) AS ntile6
--arrange the 10 rows within the 6 partition 10/6 = 1 reminder = 4 (2 rows in 4 section and 5 and 6 section have 1 row only. )
FROM CTE

rownum: It assigns a unique row number to each row based on the ascending order of thevalcolumn.rnk: It calculates the rank of each row based on the ascending order of thevalcolumn. Rows with the same value will have the same rank, and the next rank will be skipped.densernk: It calculates the dense rank of each row based on the ascending order of thevalcolumn. Rows with the same value will have the same rank, and the next rank will not be skipped.
The comments provided in the code explain the result for ntile5 and ntile6 more explicitly. For ntile5, it divides the 10 rows into 5 partitions with 2 rows in each partition. For ntile6, it divides the 10 rows into 6 partitions with 2 rows in 4 of the partitions and 1 row each in the remaining 2 partitions (due to the remainder).
Window Offset Functions
Window offset functions return an element from a single row that is in a given offset from the current row in the window partition, or from the first or last row in the window frame. T-SQL supports the following window offset functions: LAG, LEAD, FIRST_VALUE, and LAST_VALUE.
The LAG and LEAD functions rely on an offset with respect to the current row, and the FIRST_VALUE and LAST_VALUE functions operate on the first or last row in the frame, respectively.
SELECT custid, orderid, orderdate, val,
LAG(val) OVER(PARTITION BY custid ORDER BY orderdate, orderid) AS prev_val,
LEAD(val) OVER(PARTITION BY custid ORDER BY orderdate, orderid) AS next_val,
FIRST_VALUE(val) OVER(ORDER BY custid) AS FIRST_VALUE,
LAST_VALUE(val) OVER(ORDER BY custid) AS LAST_VALUE
FROM Sales.OrderValues

SELECT custid, orderid, orderdate, val,
LAG(val,3,0) OVER(PARTITION BY custid ORDER BY orderdate, orderid) AS prev_val,
LEAD(val,3,0) OVER(PARTITION BY custid ORDER BY orderdate, orderid) AS next_val,
FIRST_VALUE(val) OVER(ORDER BY custid) AS FIRST_VALUE,
LAST_VALUE(val) OVER(ORDER BY custid) AS LAST_VALUE
FROM Sales.OrderValues
