Last_value
window function doesn't
work properly.
CREATE TABLE EXAMP2
(
CUSTOMER_ID NUMBER(38) NOT NULL,
VALID_FROM DATE NOT NULL
);
Customer_id Valid_from
-------------------------------------
9775 06.04.2013 01:34:16
9775 06.04.2013 20:34:00
9775 12.04.2013 11:07:01
--------------------------------------
select DISTINCT LAST_VALUE(VALID_FROM)
OVER (partition by customer_id ORDER BY VALID_FROM ASC) rn
from examp1;
When I use LAST_VALUE
then I get following rows:
06.04.2013 20:34:00
06.04.2013 01:34:16
12.04.2013 11:07:01
When I use FIRST_VALUE
then I get following rows:
select DISTINCT FIRST_VALUE(VALID_FROM)
OVER (partition by customer_id ORDER BY VALID_FROM DESC) rn
from examp1;
4/12/2013 11:07:01 AM
First_value
query gives correct output. I hoped to get same output from these queries. Why do I have 2 different results
?
Given an ordered set of rows, FIRST_VALUE returns the value of the specified expression with respect to the first row in the window frame. The LAST_VALUE function returns the value of the expression with respect to the last row in the frame.
FIRST_VALUE is an analytic function. It returns the first value in an ordered set of values. If the first value in the set is null, then the function returns NULL unless you specify IGNORE NULLS . This setting is useful for data densification.
UNBOUNDED PRECEDING is the default. CURRENT ROW indicates the window begins or ends at the current row. UNBOUNDED FOLLOWING indicates that the window ends at the last row of the partition; offset FOLLOWING indicates that the window ends a number of rows equivalent to the value of offset after the current row.
Partition By: This divides the rows or query result set into small partitions. Order By: This arranges the rows in ascending or descending order for the partition window. The default order is ascending. Row or Range: You can further limit the rows in a partition by specifying the start and endpoints.
first_value
and last_value
are a bit special in that they require a window on which to operate.
You need to add ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
as follows:
select DISTINCT LAST_VALUE(VALID_FROM) OVER (partition by customer_id
ORDER BY VALID_FROM ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) rn
from examp1;
See the documentation: http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions001.htm#i81407 and read especially the section on windowing.
Note that the default clause for functions which accept the windowing clause is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
which explains why one order works while the other doesn't! The default clause is set this way to make it easy to do running-total type calculations without having to specify the window.
In analytic functions you need to specify window range. By default it is between unbounded preceding and current row
, which I assume to be self-explanatory.
Basically, this is what happens when you specify partition by customer_id order by valid_from asc
:
customer id
valid_from
valid_from
date, and ending with current row's valid_from
.last_value
, which returns your current row's valid_from
.What you need to do is specify an ongoing range:
16:53:00 SYSTEM@sandbox> ed
Wrote file S:\spool\sandbox\BUFFER_SYSTEM_38.sql
1 select last_value(VALID_FROM) OVER (
2 partition by customer_id
3 ORDER BY VALID_FROM asc
4 range between current row and unbounded following
5 ) rn
6* from t
16:53:21 SYSTEM@sandbox> /
RN
---------------------------------------------------------------------------
04-DEC-13 11.07.01.000000 AM
04-DEC-13 11.07.01.000000 AM
04-DEC-13 11.07.01.000000 AM
Elapsed: 00:00:00.01
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With