I am new in SQL Server. I understood the concept of ordering and getting the First value and Last value but i want to know what is the UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING? ]]>

All the best wishes …. :)

Thanks and Regards,

P.Anish Shenoy

This was wonderful quiz and we had lots of fun to evaluate it. The real difficulty was to decide who will be the winner of this contest. We first selected all the valid answers and then put the names in simple table. We picked up random name as winner.

The winner is – P.Anish Shenoy

Once again, this is not the end of puzzles which we will share with you. We will have many more and the real winning is learning new features.

Many thanks again,

Pinal

writting mistake.

Point no 2 kindly correct in my above post.

* FstValue & LstValue are generated based on – data partitined using salesorderid but order by orderqty

Regards,

]]>Well not even know detail about SQL Server 2012 only the future edition thats it.

Looking at the this + previous 2 article. I came to conclusion that

* The Order by clause at the end of statement is just sorting result produced by query

* FstValue & LstValue are generated based on – data partitined using salesorderdetailid but order by orderqty

as a result,

for salesorderid 43667 ,

there is qty order i.e. 1, 1, 1, 3 as it is ordered in the first_value()

so fstvalue is id of first salesorderdetailid that is 78 which min in qty

and lstvalue is id of salesorderdetailid that is which as max qty 3 .. so ID is 77

and above same logic applies for remaining salesorderid

Regards,

Sachin M

]]>Thank you for making this concept as puzzle.

With this puzzle concept of First_Value and Last_Value is getting more cleared.

You have changed this query (From Hint1):

SELECT s.OrderQty,s.SalesOrderID,s.SalesOrderDetailID,

FIRST_VALUE(SalesOrderDetailID) OVER (PARTITION BY SalesOrderID

ORDER BY OrderQty

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FstValue,

LAST_VALUE(SalesOrderDetailID) OVER (PARTITION BY SalesOrderID

ORDER BY OrderQty

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) LstValue

FROM Sales.SalesOrderDetail s

WHERE SalesOrderID IN (43670, 43669, 43667, 43663)

ORDER BY s.OrderQty,s.SalesOrderID,s.SalesOrderDetailID

1. Now Order of Select query is depend upon OrderQty column which is not a single value.

2. Now its cleared that First_value and Last_Value is not purely based on Min and Max value.

3. It is simply First Data and Last Data , Whether it is large value or small.

4. Second group of data is re-arranged by QrderQty like:

1 | 43667 | 78

1 | 43667 | 79

1 | 43667 | 80

3 | 43667 | 77

From above reselt set First_Value is 78 and Last Value is 77.

Regard$

Chirag Satasiya

OrderQty Sales Order ID Sales Order DetailID Fst Value Lst Value

1 43667 78 78 77

1 43667 79 78 77

1 43667 80 78 77

3 43667 77 78 77

To evalue First_VALUE it considers the first value which comes for each SalesOrderDetailsID since we used the expression “FIRST_VALUE(SalesOrderDetailID)” which is partitioned by SalesOrderID.

Similarly To evalue Last_VALUE it considers the last value which comes for each SalesOrderDetailsID since we used the expression “LAST_VALUE(SalesOrderDetailID)” which is partitioned by SalesOrderID. ]]>

Since You have mentioned “FIRST_VALUE(SalesOrderDetailID) OVER (PARTITION BY SalesOrderID

ORDER BY OrderQty” It will partition the result by SalesOrderDetailID and order it by “OrderQty”.. Which will order itself like this

43667 78 1

43667 79 1

43667 80 1

43667 77 3

From which you can see first value is 78 & last value is 77..

Hence the result is 78 & 77, and order in final result is because of the orderby at the end of the query.

]]>FIRST_VALUE(SalesOrderDetailID) OVER (PARTITION BY SalesOrderID

ORDER BY OrderQty

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FstValue

And in LAST_VALUE(SalesOrderDetailID) OVER (PARTITION BY SalesOrderID

ORDER BY OrderQty

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) LstValue

When we are using Order By Closes for “OrderQty” column its short the records as –

43667 78 1

43667 79 1

43667 80 1

43667 77 3

and work on it. (giving example for SalesOrderID – 43667 only.)

If you look on the above result First Value for SalesOrderDetailid will be – 78 and Last value will be 77, that’s why the Puzzle question is returning this type of result.

So, the FIRST_VALUE and LAST_VALUE is NOT working as MAX and MIN function respectively.

Nilesh Molankar question is very useful in solving the puzzle.

Thanks & regards

Kundan

OVER (PARTITION BY SalesOrderID

ORDER BY OrderQty

The PARTITION BY clause partitions the SalesOrderDetail by SalesOrderID and the FIRST_VALUE and LAST_VALUE function is applied to each partition independently. The ORDER BY clause specified in the OVER clause determines the logical order in which the FIRST_VALUE or LAST_VALUE function is applied to the rows in each partition. The ROWS UNBOUNDED PRECEDING clause specifies the starting point of the window as the first row of the partition.The ROWS UNBOUNDED FOLLOWING clause specifies the ending point of the window as the last row of the partition.

order by orderqty first, arrange the whole orderqty in ascending like that

SalesOrderID SalesOrderDetailID OrderQty

43667 78 1

43667 79 1

43667 80 1

43667 77 3

if you will see the first value of SalesOrderDetailID it’s 78 with OrderQty is 1,

last value of SalesOrderDetailID = 77 with OrderQty is 1.

Based on the query First value and last value are taken based on the order by clause on quantity.

The first sorted value for a particular partition by the number of quantity will be the first value

and similarly the last sorted value for a particular partition by the number of quantity will be the last value.

So according to the query and image, we are querying the first value and last value of ‘SalesOrderDetailId’ with a partition clause on ‘SalesOrderId’ and Order by clause on ‘OrderQty’.

For SalesOrderId = 43667

First Value will be = 78 and Last Value will be = 77

similarly

For SalesOrderId = 43670

First Value will be = 111 and Last Value will be = 113

One Guess here since i have not installed the SQL 2012 i am not able to test the query, according to understanding from the blog i think,

The ORDER BY keyword sort the records in ascending order by default,

if we force the order by keyword to sort the records in decending order.

Then for the same scenario above.

if we run the following query

USE AdventureWorks

GO

SELECT s.OrderQty,s.SalesOrderID,s.SalesOrderDetailID,

FIRST_VALUE(SalesOrderDetailID) OVER (PARTITION BY SalesOrderID

ORDER BY OrderQty DESC

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FstValue,

LAST_VALUE(SalesOrderDetailID) OVER (PARTITION BY SalesOrderID

ORDER BY OrderQty DESC

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) LstValue

FROM Sales.SalesOrderDetail s

WHERE SalesOrderID IN (43670, 43669, 43667, 43663)

ORDER BY s.OrderQty,s.SalesOrderID,s.SalesOrderDetailID

i guess

for SalesOrderId = 43667

First Value will be = 77 and Last Value will be = 80

similarly

For SalesOrderId = 43670

First Value will be = 112 and Last Value will be = 111

please correct me if i am wrong.

Nice Puzzle enjoying your blog posts on sql 2012 analytic functions sir.

Thanks and Regards,

P.Anish Shenoy

First_Value and Last_Value function is applied on SalesOrderDetailID with ordering on OrderQty.

First_Value returns the first value (78) available for minimum value (i.e.

1) in OrderQty.

Last_Value returns the Last value (77) available for maximum value (i.e. 3) in OrderQty.

]]>Using order by on orderqty first, arrange the whole data in ascending order of orderqty field which give us values 1,1,1,3 with SalesOrderDetailsID as 78,79,80,77 respectively (only for SalesOrderID =43667)

So it shows,the first_value is 78 and last_value is 77 in the result set.

]]>At the time we had “ORDER BY OrderQty” statement, It first sort records based on OrderQty column in Ascending order so first, all records with qty. 1 (lowest qty) would come and than orders with qty. 3 (maximum records of highest qty) would come. Now, if you will see the first value (minimum value) of SalesOrderDetailsID whose OrderQty is 1, you would find 78 which would be our Firstvalue detected by the function then it comes to the biggest OrderQty which is 3 and if you find maximum number of salesOrderDetailsID whose OrderQty is 3 then you would find 77.

This is the reason we are getting FirstValue as 78 and LastValue as 77

]]>I think the order by in over clause is arranging the result according to the OrderQty with will result in arrangement in ascending order.

i.e we have values OrderQty 1,1,1,3 with SalesOrderDetailsID as 78,79,80,77 respectively.

So the first_value is 78 and last_value is 77 in the result set when we have order by OrderQty in the Over clause.

Lastly final ORDER BY s.SalesOrderID,s.SalesOrderDetailID,s.OrderQty is only used to arrange the final result set, so that the result is understandable.

It arranges the result set in ascending order first by s.SalesOrderID,s.SalesOrderDetailID,s.OrderQty respectively.

Your Sincerely,

Yeou Sunn Liu

]]>