In SQL Server, FIRST_VALUE()
is a window function that returns the first value in an ordered set of values.
Basically, we can use it to get a value from the first row of a query result set or partition. This can be handy if we want to compare a value in the current row with a value in the first row, or use it as part of a calculation.
Example
Here’s an example of using the FIRST_VALUE()
function:
SELECT
VendorId,
ProductName,
ProductPrice,
FIRST_VALUE( ProductPrice ) OVER (
ORDER BY ProductPrice
) AS FIRST_VALUE
FROM Products;
Result:
VendorId ProductName ProductPrice FIRST_VALUE -------- ------------------------------- ------------ ----------- 1004 Bottomless Coffee Mugs (4 Pack) 9.99 9.99 1003 Hammock 10 9.99 1001 Long Weight (green) 11.99 9.99 1004 Tea Pot 12.45 9.99 1001 Long Weight (blue) 14.75 9.99 1001 Left handed screwdriver 25.99 9.99 1001 Right handed screwdriver 25.99 9.99 1002 Sledge Hammer 33.49 9.99 1003 Straw Dog Box 55.99 9.99 1003 Chainsaw 245 9.99
Here, the FIRST_VALUE
column displays the first value of the ProductPrice
column when sorted in ascending order. That is, it returns the value from the first row.
Here’s an example of using this function to find out the price difference between the cheapest product and the current product:
SELECT
VendorId,
ProductName,
ProductPrice,
FIRST_VALUE( ProductPrice ) OVER (
ORDER BY ProductPrice
) AS FIRST_VALUE,
ProductPrice - FIRST_VALUE( ProductPrice ) OVER (
ORDER BY ProductPrice
) AS Premium
FROM Products;
Result:
VendorId ProductName ProductPrice FIRST_VALUE Premium -------- ------------------------------- ------------ ----------- ------- 1004 Bottomless Coffee Mugs (4 Pack) 9.99 9.99 0 1003 Hammock 10 9.99 0.01 1001 Long Weight (green) 11.99 9.99 2 1004 Tea Pot 12.45 9.99 2.46 1001 Long Weight (blue) 14.75 9.99 4.76 1001 Left handed screwdriver 25.99 9.99 16 1001 Right handed screwdriver 25.99 9.99 16 1002 Sledge Hammer 33.49 9.99 23.5 1003 Straw Dog Box 55.99 9.99 46 1003 Chainsaw 245 9.99 235.01
We sorted by the ProductPrice
column in ascending order, therefore the first row contains the cheapest product. Therefore we were able to deduct that value from each subsequent row to find out the price premium of each subsequent product.
Partitioning the Result Set
As with any window function, we can use a PARTITION BY
clause in order to partition the result set by a given column. For example, we can partition by vendor:
SELECT
v.VendorName,
p.ProductName,
p.ProductPrice,
FIRST_VALUE( ProductPrice ) OVER (
PARTITION BY p.VendorId
ORDER BY p.ProductPrice
) AS FIRST_VALUE
FROM Products p
INNER JOIN Vendors v
ON v.VendorId = p.VendorId;
Result:
VendorName ProductName ProductPrice FIRST_VALUE ------------- ------------------------------- ------------ ----------- Mars Supplies Long Weight (green) 11.99 11.99 Mars Supplies Long Weight (blue) 14.75 11.99 Mars Supplies Left handed screwdriver 25.99 11.99 Mars Supplies Right handed screwdriver 25.99 11.99 Randy Roofers Sledge Hammer 33.49 33.49 Pedal Medals Hammock 10 10 Pedal Medals Straw Dog Box 55.99 10 Pedal Medals Chainsaw 245 10 Katty Kittens Bottomless Coffee Mugs (4 Pack) 9.99 9.99 Katty Kittens Tea Pot 12.45 9.99
Here we get the first value within each partition. Our FIRST_VALUE
column resets with each new partition.
In this case I used a SQL join to join the Products
and Vendors
table so that I could present the vendor names instead of just their IDs.
The OVER
Clause is Required
We must provide the OVER
clause when using window functions such as FIRST_VALUE()
. Here’s what happens if we remove it:
SELECT
VendorId,
ProductName,
ProductPrice,
FIRST_VALUE( ProductPrice )
FROM Products;
Result:
Msg 10753, Level 15, State 1, Line 5 The function 'FIRST_VALUE' must have an OVER clause.
The ORDER BY
Clause is Required
Not only must we provide an OVER
clause, but that clause must have an ORDER BY
clause. Here’s what happens when we include an OVER
clause without an ORDER BY
clause:
SELECT
VendorId,
ProductName,
ProductPrice,
FIRST_VALUE( ProductPrice ) OVER( )
FROM Products;
Result:
Msg 4112, Level 15, State 1, Line 5 The function 'FIRST_VALUE' must have an OVER clause with ORDER BY.
Documentation
For more information and examples, see Microsoft’s documentation for the FIRST_VALUE() function.