Analytical functions: FIRST vs FIRST_VALUE
Hello
Can someone please help me understand the difference between PRIME and FIRST_VALUE in Anaytic functions.
I tried below 2 queries, but I see the same output. The only difference I see is that the field of the SAL is ordered FIRST_VALUE, but not the FIRST.
SELECT ename,
DEPTNO,
SAL,
MIN (SAL) keep (dense_rank FIRST
ORDER BY sal) by (deptno partition) FIRST
EMP;
SELECT ename,
DEPTNO,
SAL,
FIRST_VALUE (SAL) over (partition BY deptno arrested by sal) FIRST
EMP;
With the help of: Windows 8.1
Database Oracle 12 c Enterprise Edition Release 12.1.0.1.0 - 64 bit Production
PL/SQL Release 12.1.0.1.0 - Production
"CORE 12.1.0.1.0 Production."
AMT for 64-bit Windows: Version 12.1.0.1.0 - Production
NLSRTL Version 12.1.0.1.0 - Production
Hello
Here is an example of when you can use the FIRST analytic function.
Say you want the average sal for each Department, but only for the first year (taken from the hiredate column) in the Department (i.e., the column called f in the query below).
WITH got_hireyear AS
(
SELECT deptno and ename, sal, hiredate
EXTRACT (YEAR FROM hiredate) AS hireyear
FROM scott.emp
)
SELECT deptno, hireyear, hiredate, ename, sal
AVG (sal) DUNGEON (DENSE_RANK FIRST ORDER BY hireyear)
COURSES (PARTITION BY deptno
) In the FORM f
FIRST_VALUE (sal) over (PARTITION BY deptno
ORDER BY hireyear
) AS fv
AVG (sal) over (PARTITION BY deptno
hireyear
), A
OF got_hireyear
ORDER BY deptno
hireyear
ename
;
Output:
HIREYEAR ENAME SAL HIREDATE DEPTNO F FV HAS
------ ---------- ----------- ---------- ------ --------- ------ ---------
10 1981 9 June 1981 CLARK 2450 2450 3725,00 3725.00
10 1981 17 November 1981 KING 5000 3725,00 2450 3725.00
10 1982 23 January 1982 MILLER 1300 3725,00 2450 1300.0020, 1980, 17 December 1980 SMITH 800 800.00 800.00 800
20, 1981, 3 December 1981 FORD 3000 800.00 800 2987.50
20, 1981, 2 April 1981 JONES 2975 800.00 800 2987.50
20, 1987, 23 May 1987 ADAMS 1100 800.00 800 2050.00
20, 1987, 19 April 1987 SCOTT 3000 800.00 800 2050.0030 1981 20 February 1981 ALLEN 1600 1566.67 950 1566.67
May 30 1981 1st 1981 BLAKE 2850 1566.67 950 1566.67
December 30 1981 3 1981 JAMES 950 1566.67 950 1566.67
30 1981 28 - sep - 1981 MARTIN 1250 1566.67 950 1566.67
30-08 - sep - 1981 1981 TURNER 1500 1566.67 950 1566.67
30 1981 22 February 1981 WARD 1250 1566.67 950 1566.67
The analytical FIRST_VALUE function can do (except in the very special case where only 1 row has the lowest hireyear, as in deptno = 20). AVG analysis can do (except in the very special case that all lines have the same hireyear as in deptno = 30).
Tags: Database
Similar Questions
-
FIRST_VALUE() and LAST_VALUE Analytic Functions
Hi all
May be that it is a fundamental issue. But I'm having a hard time understanding the difference between FIRST_VALUE() and LAST_VALUE() of analytical functions.
As much as what I read the FIRST_VALUE function picks up the first record after the partition and order by and he returned after all calculation. And the LAST_VALUE does the opposite. But the result of the second query as I expected, are not (last value of the partition). It would be useful that someone could throw some light on it.
select empno , ename , sal , first_value(ename) over(order by sal desc) from emp; empno ename sal first_value ------ ---------- --------- ----------- 7839 KING 5000.00 KING 7902 FORD 3000.00 KING 7788 SCOTT 3000.00 KING 7566 JONES 2975.00 KING 7698 BLAKE 2850.00 KING 7782 CLARK 2450.00 KING 7499 ALLEN 1600.00 KING 7844 TURNER 1500.00 KING 7934 MILLER 1300.00 KING 7654 MARTIN 1250.00 KING 7521 WARD 1250.00 KING 7876 ADAMS 1100.00 KING 7900 JAMES 950.00 KING 7369 SMITH 800.00 KING 14 Row(s) affected
Thank youselect empno , ename , sal , last_value(ename) over(order by sal desc) from emp; empno ename sal last_value ------ ---------- --------- ---------- 7839 KING 5000.00 KING 7902 FORD 3000.00 SCOTT 7788 SCOTT 3000.00 SCOTT 7566 JONES 2975.00 JONES 7698 BLAKE 2850.00 BLAKE 7782 CLARK 2450.00 CLARK 7499 ALLEN 1600.00 ALLEN 7844 TURNER 1500.00 TURNER 7934 MILLER 1300.00 MILLER 7521 WARD 1250.00 MARTIN 7654 MARTIN 1250.00 MARTIN 7876 ADAMS 1100.00 ADAMS 7900 JAMES 950.00 JAMES 7369 SMITH 800.00 SMITH 14 Row(s) affected
VincentHey, Vincent,.
When you use an analytic function with an ORDER BY clause, the results will be based on a window, which is a subset of the partition.
If you do not specify a window (using the keywords LINE or LINES) the window everything will be in order by the ORDER BY clause, until and including the current line, including links.For example, in your second query:
select empno , ename , sal , last_value(ename) over(order by sal desc) from emp; empno ename sal last_value ------ ---------- --------- ---------- 7839 KING 5000.00 KING 7902 FORD 3000.00 SCOTT 7788 SCOTT 3000.00 SCOTT 7566 JONES 2975.00 JONES 7698 BLAKE 2850.00 BLAKE 7782 CLARK 2450.00 CLARK 7499 ALLEN 1600.00 ALLEN 7844 TURNER 1500.00 TURNER 7934 MILLER 1300.00 MILLER 7521 WARD 1250.00 MARTIN 7654 MARTIN 1250.00 MARTIN 7876 ADAMS 1100.00 ADAMS 7900 JAMES 950.00 JAMES 7369 SMITH 800.00 SMITH
The analytic function
last_value(ename) over(order by sal desc)
Returns the last ename, not of the entire table, but the window starting with the highest sal (since you say "ORDER BY sal DESC") and including the current line and all the other lines that have the same sal.
So consider the 1st row, ename = 'KING '. It has the most sal, so that a single line in the window, 'KING' IS THE LAST VALUE WINDOW.
Now consider the 2nd row, where ename = 'FORD' and sal = 3000. The window includes now everybody with a sal of 3000 and more, which means the 3 rows 'KING', 'FORD' and 'SCOTT '. The last of them (in descending order of sal) is 'SCOTT '. (In fact, there is a tie, you could just as well say that "JONES" is changed, because there is a tie between the two rows where sal = 3000) When this happens, one of the lines will arbitrarily designate the "last" line don't expect not to be always the same line.)
Because of this, LAST_VALUE is alwmost always used with an explicit windowing clause, beginning with the BEACH or LINES.
If you want a request as your first request, but it contains the name of the lowest paid employee (that is, he always says 'SMITH' in the last column instead of 'KING'), then use FIRST_VALUE, but reverse the sort order:
first_value(ename) over(order by sal ASC)
-
Return one row of an analytic function
Hello
I pulled the following query:
Select ID_STORNO, first_value (COD_CONTATTO) ON (Partition of COD_CONTATTO
order of COD_PRIORITY asc, desc FT_DAT_OPEN_CNT
rows between unbounded preceding and following unbounded)
as COD_CONTATTO_LAST
of WT_STR_ESG_CONTATTO;
The result is:
2160603 C1-H83J1N 2160603 C8-9FOHXJS 2258072 C1-H83J1N But I just need to take the following lines
2160603 C8-9FOHXJS 2258072 C1-H83J1N Because for the same value of ID_STORNO, I just need to get a value of COD_CONTATTO (to select the best value using COD_PRIORITY and FT_DAT_OPEN_CNT). What is wrong inside the query? I just use 2 or 3 times the oracle analytic functions.
Best regards
As SomeoneElse... you need a where clause clause in order to choose the ones you want.
To do this, the typical is to select a column that you use for this reason, such as:
"I want to just the first record in each group..."
Select id_storno, cod_contatto_last from)
Select ID_STORNO, first_value (COD_CONTATTO) ON (Partition of COD_CONTATTO
order of COD_PRIORITY asc, desc FT_DAT_OPEN_CNT
rows between unbounded preceding and following unbounded)
as COD_CONTATTO_LAST,
ROW_NUMBER() OVER (Partition of COD_CONTATTO
order of COD_PRIORITY asc, desc FT_DAT_OPEN_CNT
rows between unbounded preceding and following unbounded)
as rnum
of WT_STR_ESG_CONTATTO
)
where rnum = 1
/
I prefer to use rownumber in this case, so I always have a rnum = 1...
Usually, you must use the same partition/command by as your other folders (it is usually a good idea... maybe not, depending on your needs, however)
-
Which analytical function to use?
Hi gurus,DB - Oracle 11 g 2
I followed the examples of data in the table test_a.
col1 col2 col3
----- ------- --------
x y y
p q y
a b y
p q y
t r y
p q y
The col3 column is always 'y '. But here's the data p, q, there is repeated 3 times (duplicate) and if this is the case I want to update only the first recordings like "n" col3 it is to say p, q, n. rest will be as it is.
I am able to get the row_number() for it but not able to do this.
Select col1, clo2, clo3 row_number() over (partition by col2) arrested by col1 as test_a r_num
Would it be possible directly by any analytic function?
Thank you
SID
COL4 is logical...
Something like that?
with x as)
Select col1, col2 ' x' 'y', 'y' col3 col4 1 Union double all the
Select 'p' col1, col2 'q', 'y' col3 col4 2 Union double all the
Select 'a' col1, col2 'b', 'y' col3 col4 3 of all the double union
Select 'p' col1, col2 'q', 'y' col3 col4 4 Union double all the
Select 't' col1, col2 'r', 'y' col3, col4 5 Union double all the
Select 'p' col1, col2 'q', 'y' col3 col4 6 double
)
---
Select * from)
Select x.*,
ROW_NUMBER() on rn1 (score of col1, col2, col3 col4 sort),
ROW_NUMBER() on rn2 (partition by col1, col2, col3 col4 desc sorting)
x
)
where rn1 = 1 and rn2 <> 1;
Understand the logic and simply change SELECT a query to UPDATE...
-
Nth salary using the analytic function
I use under function to calculate second highest with empno and deptno salary.
Is it possible to get the same result with another query without using Assembly only analytical functions condition.using and windows function is possible to get the desired output?
SELECT e.empno,
e.DEPTNO,
tmp. SAL as second_higher_salary
FROM emp e,.
(SELECT Empno,
DEPTNO,
SAL,
DENSE_RANK() (PARTITION BY deptno ORDER of sal) AS rnk
WCP
) tmp
WHERE tmp.deptno = e.deptno
and tmp.rnk = 2
EMPNO DEPTNO SAL
---------- ---------- ----------
7934 10 2450
7782 10 2450
7839 10 2450
7876 20 1100
7369 20 1100
7902 20 1100
7788 20 1100
7566 20 1100
7900 30 1250
7844 30 1250
7654 30 1250
7521 30 1250
7499 30 1250
7698 30 1250
7900 30 1250
7844 30 1250
7654 30 1250
7521 30 1250
7499 30 1250
7698 30 1250
Here's my solution:
Select empno,
DEPTNO,
FIRST_VALUE (sal) (PARTITION BY deptno ORDER by sal desc)
de)
SELECT EmpNo,
DEPTNO,
Decode (DENSE_RANK () OVER (PARTITION BY deptno order by sal desc), 1,-sal, sal) sal
WCP
)
/
EMPNO DEPTNO FIRST_VALUE (SAL) OVER (PARTITIONBYDEPTNOORDERBYSALDESC) ---------- ---------- -----------------------------------------------------
7782 10 2450 7934 10 2450 7839 10 2450 7566 20 2975 7876 20 2975 7369 20 2975 7788 20 2975 7902 20 2975 7499 30 1600 7844 30 1600 7654 30 1600 7521 30 1600 7900 30 1600 7698 30 1600 -
Hello
I have two tables b rates and transactions (b).
For each b.FS, I want to know new amount (b.amt time a.rate to the corresponding line of FS b and if a.na is valid based on the flag of the exclusion and the interval defined in the table's).
It is much easier to explain with an example.
So here we go...
Exclude_flag = E (exclude): for b.fs = 433638, b.na = 80000. I have 2 lines in the table for this fs. Both have E exclude_flag (exclude). I want to go on all the lines in this FS in the table in a query and I return only one row in the result, if and only if b.na falls out of scope of a.na_min_value and a.na_max_values. In this example, it falls outside the range excluded for both lines (first two lines of the table a).
Similarly, exclude_flag = I (Include). for b.fs = 432828, b.na = 17200. I have 2 lines in the table for this fs. Both have an exclude_flag of I (include). I want to go on all the lines in this FS in the table in a query and I return only one row in the result, if and only if b.na is between a.na_min_value and a.na_max_values. In this example, it falls in the range of both the range include for the two lines (line 6 and 7 of the table a).
The following query gives me two lines for each b.fs. It is possible to get what I'm looking for simply using sql (possibly write the analytical function?) or I have to write the pl/sql routine for this?
WITH rates_table
Did YOU (select ' E' include_exclude_flag, "81000 ' na_min_value, na_max_value '81999', '433638' FS, 0.8 of double rate
UNION
Select 'E' include_exclude_flag, na_min_value '84000', na_max_value '84999', '433638' FS, 0.8 of double rate
UNION
Select 'I' include_exclude_flag, na_min_value '12000', na_max_value '12999', '432828' FS, rate 0.25 double
UNION
Select 'I' include_exclude_flag, na_min_value '13000', na_max_value '13999', '432828' FS, rate 0.25 double
UNION
Select 'I' include_exclude_flag, na_min_value '15000', na_max_value '15000', '432828' FS, rate 0.25 double
UNION
Select 'I' include_exclude_flag, na_min_value '16100', na_max_value '18000', '432828' FS, rate 0.25 double
UNION
Select 'I' include_exclude_flag, '17100' na_min_value, na_max_value '18000', '432828' FS, rate 0.25 double
UNION
Select 'I' include_exclude_flag, na_min_value '02440', na_max_value '02470', '016532' FS, 0.35 rate double
UNION
Select 'E' include_exclude_flag, na_min_value ' 21000 ', '21000' na_max_value, ' 200020' FS, 0.35 double rate).
transaction_table AS
(select '433638' FS '80000' NA, 300 double amt)
Union
Select '432828' FS '17200' NA, amt 500 double
)
Select * from rates_table a, transaction_table b
where 1 = 1
and ((b.na PAS entre a.na_min_value et a.na_max_value et a.include_exclude_flag = «E») GOLD ())
b.na between a.na_min_value and a.na_max_value and a.include_exclude_flag = 'I'))
and b.fs = a.fs
;
Any help is greatly appreciated. I use oracle 11i
@OP,
For this kind of problems, we get the number of rows that satisfy the required conditions or who do not meet the required conditions. And then eliminate the line that should be eliminated.
As below, I calculate four counts (number of join lines)
EOBCNT - excluded and Out of Bound
EIBCNT - excluded and in the limit
IOBCNT - included and Out of Bound
IIBCNT - included and within the limits
Once those are calculated, simply return the lines that have EIBCNT and IOBCNT are zero.
For Ex:
> WITH
rates_table
AS LONG AS)
Select 'E' include_exclude_flag, na_min_value '79999', na_max_value '79999', '433638' FS, 0.8 double UNION rates
-Select 'E' include_exclude_flag, na_min_value ' 79999', na_max_value '80000', '433638' FS, 0.8 double UNION rate - TEST - THE
-If you uncomment the last line and then 433638 will not be returned
Select 'E' include_exclude_flag, "81000 ' na_min_value, na_max_value '81999', '433638' FS, 0.8 double UNION rates
Select 'E' include_exclude_flag, na_min_value '84000', na_max_value '84999', '433638' FS, 0.8 double UNION rates
Select 'I' include_exclude_flag, na_min_value '12000', na_max_value '12999', '432828' FS, 0.25 rate double UNION
Select 'I' include_exclude_flag, na_min_value '13000', na_max_value '13999', '432828' FS, 0.25 rate double UNION
Select 'I' include_exclude_flag, na_min_value '15000', na_max_value '15000', '432828' FS, 0.25 rate double UNION
Select 'I' include_exclude_flag, na_min_value '16100', na_max_value '18000', '432828' FS, 0.25 rate double UNION
Select 'I' include_exclude_flag, '17100' na_min_value, na_max_value '18000', '432828' FS, 0.25 rate double UNION
Select 'I' include_exclude_flag, na_min_value '02440', na_max_value '02470', '016532' FS, 0.35 rate double UNION
Select 'E' include_exclude_flag, na_min_value ' 21000 ', '21000' na_max_value, ' 200020' FS, 0.35 double rate).
transaction_table AS
(select '433638' FS '80000' NA, amt 300 Union double
Select '432828' FS '17200' NA, amt 500 double
)
getcnts as)
SELECT a.*
b.na, b.amt
, sum (case when (b.na NOT BETWEEN a.na_min_value)
AND a.na_max_value
AND a.include_exclude_flag = 'E '.
end) then 1 else 0) on (a.fs partition) Eobcnt
, sum (case when (b.na NOT BETWEEN a.na_min_value)
AND a.na_max_value
AND a.include_exclude_flag = 'I '.
end) then 1 else 0) on (a.fs partition) Iobcnt
, sum (case when (b.na BETWEEN a.na_min_value)
AND a.na_max_value
AND a.include_exclude_flag = 'E '.
end) then 1 else 0) on (a.fs partition) Eibcnt
, sum (case when (b.na BETWEEN a.na_min_value)
AND a.na_max_value
AND a.include_exclude_flag = 'I '.
end) then 1 else 0) on (a.fs partition) Iibcnt
OF rates_table one
transaction_table b
WHERE b.fs = a.fs
)
getrows as)
Select x.*, row_number() on
(partition by order of fs with null desc) getcnts rn x
where IOBCNT = 0 and eibcnt = 0 - remove lines that are not needed (IF and ONLY if)
)
Select * from getrows
where rn = 1 - to limit a SINGLE row (arbitrarily)
INCLUDE_EXCLUDE_FLAG NA_MIN_VALUE NA_MAX_VALUE FS RATE NA AMT EOBCNT IOBCNT EIBCNT IIBCNT RN
-------------------- ------------ ------------ ------ ---------- ----- ---------- ---------- ---------- ---------- ---------- ----------
433638 84999 84000.8 E 80000 300 3 0 0 0 1
I hope this helps.
-
Order of evaluation of analytic function
Hello
have question quite like this:
with
-This query selects a 'representative' acct_id by Group (about 300 lines in total)
acct_repres as
(
Select distinct acct_id, origin_id, acct_parm_id of
(
Select a.*
source_id
, dense_rank() over (partition by order source_id by nulls first, acct_id acct_nbr origin_id) as odr
account a join account_parm on (a.parm_id = ap.acct_parm_id) ap
)
where odr = 1
)
Select col1
col2
, (select accct_id from ar acct_repres where ar.acct_parm_id = t2.acct_parm_id) col3
, col4 (select count (1) of acct_repres)
of une_table t1
Join other_table t2 on (...)
And here it is. "Acct_repres" subquery returns more than 300 lines when it is run separately. But when it is used in CTE sometimes (depending on the execution plan) she seems to have that one line - the value in the column col4 is '1 ',.
While the value of col3 is NULL for most of the cases.
It looks like the the dense_rank function and the State 'where odr = 1' are evaluated at the end.
When I use the hint to MATERIALIZE the result was the same.
But when I put the result of account_repres in the dedicated table and use this table instead of CTE output is correct.
What is a bug? Or I do something wrong?
PS: my version of db is 11 GR 1 material (11.1.0.7).
some unorganized comments:
-analytical functions are evaluated towards the end of the execution ("' the last set of operations performed in a query with the exception of the final
ORDER
BY
clause"- http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions004.htm")-but still the result of a SQL query must be deterministic, so I think that your results are not an expected behavior
-the CBO has some problems with common table expressions (http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/) if they are of great assistance in the structuring of complex queries. In these cases, you can avoid problems by using inline views
-Your query uses the common table expressions in scalar subqueries and scalar subqueries are also likely to confuse the CBO. In addition, they are executed once for each row in your result set (or at least for each different correlation value) and can have a negative impact on the performance of the queries in many cases. Often, they can be replaced by outer joins.
-you say that the suspicion of materialization brings you an erroneous result: the indicator object (online) gives you the correct results?
Concerning
Martin Preiss
-
Is there a shorter way (better) with analytical functions?
Here's a little test scenario:
For each id, I want to add all the values of m only when they have a different type. It would be a long journey:create table t ( id number, pos number, typ number, m number); insert into t values (1,1,1,100); insert into t values (1,2,1,100); insert into t values (1,3,2, 50); insert into t values (2,1,3, 30); insert into t values (2,2,4, 70); insert into t values (3,1,1,100); insert into t values (3,2,2, 50); insert into t values (4,1,3, 30); insert into t values (4,2,5, 80); insert into t values (4,3,3, 30); insert into t values (5,1,3, 30); insert into t values (5,2,6, 30); insert into t values (6,1,2, 50); insert into t values (6,2,7, 50); insert into t values (6,3,2, 50); insert into t values (7,1,4, 70); insert into t values (7,2,4, 70); insert into t values (7,3,4, 70);
but I wonder, is it possible to get this result with a single statement select using analytic functions, something likewith t1 as (select id, typ, min(m) m1 from t group by id, typ) select id, sum(m1) f from t1 group by id order by 1; ID F ---------- ---------- 1 150 2 100 3 150 4 110 5 60 6 100 7 70
select id, sum(m) over (partition by distinct typ) F -- this does not work. It's only an idea how it might look like from t group by id;
This is firstly a collection with the id, type with calculation of the min for each id, type the combination.
By subsequently for each id of the sum of the minutes (for each combination of id, type for this particular id) is summarized.select distinct id, sum(min(m)) over (partition by id) from data group by id, typ order by id
Published by: chris227 on 15.03.2013 07:39
-
Here is an example of the table data:
I would get this:ID NAME Start 1 SARA 01-JAN-2006 2 SARA 03-FEB-2006 3 LAMBDA 21-MAR-2006 4 SARA 13-APR-2006 5 LAMBDA 01-JAN-2007 6 LAMBDA 01-SEP-2007
I tried using partition and run the function but partition name combines all the lines of Sara and Lambda lines into a single group/partition that is not I am trying to get.Name Start Stop SARA 01-JAN-2006 20-MAR-2006 LAMBDA 21-MAR-2006 12-APR-2006 SARA 13-APR-2006 31-DEC-2006 LAMBDA 01-JAN-2007 <null>
Is there an analytic function or other means to achieve to combine date ranges only when the same person appeared conescutively?
Thank you.This can be easily achieved using tabibitosan:
First of all, you need to identify 'groups', that each name in the list belongs
with sample_data as (select 1 id, 'SARA' name, to_date('01/01/2006', 'dd/mm/yyyy') start_date from dual union all select 2 id, 'SARA' name, to_date('03/02/2006', 'dd/mm/yyyy') start_date from dual union all select 3 id, 'LAMBDA' name, to_date('21/03/2006', 'dd/mm/yyyy') start_date from dual union all select 4 id, 'SARA' name, to_date('13/04/2006', 'dd/mm/yyyy') start_date from dual union all select 5 id, 'LAMBDA' name, to_date('01/01/2007', 'dd/mm/yyyy') start_date from dual union all select 6 id, 'LAMBDA' name, to_date('01/09/2007', 'dd/mm/yyyy') start_date from dual) select id, name, start_date, lead(start_date, 1, to_date('31/12/9999', 'dd/mm/yyyy')) over (order by start_date) next_start_date, row_number() over (order by start_date) - row_number() over (partition by name order by start_date) grp from sample_data; ID NAME START_DATE NEXT_START_DATE GRP ---------- ------ ---------- --------------- ---------- 1 SARA 01/01/2006 03/02/2006 0 2 SARA 03/02/2006 21/03/2006 0 3 LAMBDA 21/03/2006 13/04/2006 2 4 SARA 13/04/2006 01/01/2007 1 5 LAMBDA 01/01/2007 01/09/2007 3 6 LAMBDA 01/09/2007 31/12/9999 3
You can see the group number is generated by comparing the rownumber overall of all lines (in order) with the rownumber of the rowset by name (in the same order) - when there is a gap because another name appears between the two, the group number changes.
Once you have identified the number of group for each set of rows, it is easy to find the min / max values in this group:
with sample_data as (select 1 id, 'SARA' name, to_date('01/01/2006', 'dd/mm/yyyy') start_date from dual union all select 2 id, 'SARA' name, to_date('03/02/2006', 'dd/mm/yyyy') start_date from dual union all select 3 id, 'LAMBDA' name, to_date('21/03/2006', 'dd/mm/yyyy') start_date from dual union all select 4 id, 'SARA' name, to_date('13/04/2006', 'dd/mm/yyyy') start_date from dual union all select 5 id, 'LAMBDA' name, to_date('01/01/2007', 'dd/mm/yyyy') start_date from dual union all select 6 id, 'LAMBDA' name, to_date('01/09/2007', 'dd/mm/yyyy') start_date from dual), tabibitosan as (select id, name, start_date, lead(start_date, 1, to_date('31/12/9999', 'dd/mm/yyyy')) over (order by start_date) next_start_date, row_number() over (order by start_date) - row_number() over (partition by name order by start_date) grp from sample_data) select name, min(start_date) start_date, max(next_start_date) stop_date from tabibitosan group by name, grp order by start_date; NAME START_DATE STOP_DATE ------ ---------- ---------- SARA 01/01/2006 21/03/2006 LAMBDA 21/03/2006 13/04/2006 SARA 13/04/2006 01/01/2007 LAMBDA 01/01/2007 31/12/9999
If you want the date to appear as null max, you will need to use a cast or decode to change it - I'll leave that as an exercise for you to do! I'll also let you to find how to get the day before for the stop_date.
-
application of analytic function
SELECT C, CAL Table;
THE OUTPUT IS:
C CAL
C1 701
C1 702
C1 703
C2 701
C2 702
C3 701
C3 702
C3 703
I want using the analytical function and
get outside like below
C CAL
C1 703
C2 702
C3 703
Please guide me how I can get
Thank youHello
with data as ( select 'C1' C, 701 CAL from dual union all select 'C1', 702 from dual union all select 'C1', 703 from dual union all select 'C2', 701 from dual union all select 'C2', 702 from dual union all select 'C3', 701 from dual union all select 'C3', 702 from dual union all select 'C3', 703 from dual ) select c ,max(cal) from data group by c C;MAX(CAL) C1;703 C2;702 C3;703 You can do this with analytics e.g. select c ,max(cal) keep (dense_rank first order by c) over (partition by c ) cal from dat C;CAL C1;703 C1;703 C1;703 C2;702 C2;702 C3;703 C3;703 C3;703 but then you will always do a distinct finally select distinct c ,max(cal) keep (dense_rank first order by c) over (partition by c ) cal from data C;CAL C3;703 C2;702 C1;703 Therefore, at last, you will prefer the group by anyway :-)
Concerning
-
the date of consolidation extends using analytic functions
I am trying to establish how long a person was in a situation the data looks like this
person Locator recorded_date
--------------------------------------------------------
01/01/2012 10:10 LOC_A PERSON_X
03/01/2012 PERSON_X LOC_A 15:10
04/01/2012 PERSON_X LOC_B 02:00
05/01/2012 PERSON_X LOC_B 11:10
06/01/2012 PERSON_X LOC_A 03:10
What I want in the output. I want to divide it into 3 bays. What do I get with min and rank is a grouping of the last loc_a with the first that goes on the average time they were in a different location.
Start anyone to date date stop
-----------------------------------------------------------------------------------
01/01/2012 10:10 01/04/2012 PERSON_X LOC_A 02:00
04/01/2012 02:00 06/01/2012 PERSON_X LOC_B 03:10
06/01/2012 PERSON_X LOC_A 03:10Hello
DanU says:
Thanks Frank! This was extremely helpful. I probably get the final stages. The only piece I am missing is having the end defined by the following date recorded date. So I might try your query with the lead function.Sorry, I don't have the sense of end_date.
You're right; all you need is the analytical function of LEAD to get:WITH got_grp AS ( SELECT recorded_date, cqm_category, pat_acct_num , ROW_NUMBER () OVER ( PARTITION BY pat_acct_num ORDER BY recorded_date ) - ROW_NUMBER () OVER ( PARTITION BY pat_acct_num , cqm_category ORDER BY recorded_date ) AS grp FROM export_table ) SELECT MIN (recorded_date) AS start_date , LEAD (MIN (recorded_date)) OVER ( PARTITION BY pat_acct_num ORDER BY MIN (recorded_date) ) AS stop_date , cqm_category , pat_acct_num FROM got_grp GROUP BY pat_acct_num, cqm_category, grp ORDER BY pat_acct_num, start_date ;
It's almost the same query as what I posted before.
Apart from substituting your new table and column names, the only change I made was how stop_date is defined in the main query. -
Hello
I use under request
Select * from
(
SELECT FLAG, S_DATE, ROW_NUMBER () OVER (PARTITION OF)
order by S_DATE, FLAG flag) d
Table_name FROM
ORDER BY S_DATE
);
below the output which gives
Flag | S_DATE | D
Y | 27/02/2012 05:33 | 1
Y | 27/02/2012 05:34 | 2
Y | 27/02/2012 05:34 | 3
N | 27/02/2012 05:34 | 1
N | 27/02/2012 05:34 | 2
N | 27/02/2012 05:34 | 3
N | 27/02/2012 05:35 | 4
N | 27/02/2012 05:35 | 5
Y | 27/02/2012 05:36 | 4
Y | 27/02/2012 05:36 | 5
Y | 27/02/2012 05:36 | 6
But I want the output to be below order is changed in the last 3 rows
Flag | S_DATE | D
Y | 27/02/2012 05:33 | 1
Y | 27/02/2012 05:34 | 2
Y | 27/02/2012 05:34 | 3
N | 27/02/2012 05:34 | 1
N | 27/02/2012 05:34 | 2
N | 27/02/2012 05:34 | 3
N | 27/02/2012 05:35 | 4
N | 27/02/2012 05:35 | 5
Y | 27/02/2012 05:36 | 1
Y | 27/02/2012 05:36 | 2
Y | 27/02/2012 05:36 | 3
I used the analytical function.
Published by: user8858890 on February 27, 2012 02:00Hello
user8858890 wrote:
... But I want the output to be below order is changed in the last 3 rowsFlag | S_DATE | D
Y | 27/02/2012 05:33 | 1
Y | 27/02/2012 05:34 | 2
Y | 27/02/2012 05:34 | 3
N | 27/02/2012 05:34 | 1
N | 27/02/2012 05:34 | 2
N | 27/02/2012 05:34 | 3
N | 27/02/2012 05:35 | 4
N | 27/02/2012 05:35 | 5
Y | 27/02/2012 05:36 | 1
Y | 27/02/2012 05:36 | 2
Y | 27/02/2012 05:36 | 3Why do you want the last 3 lines (who have the flag = 'Y') to be numbered 1, 2, 3, when the first 3 lines (who also have the flag = "Y") already have the numbers 1, 2 and 3? Do you want a separate whenevever #1 there is a group of consecutive lines (when ordered by s_date) who have the same flag? If so, you need to identify the groups, like this:
WITH got_grp_id AS ( SELECT flag , s_date , ROWID AS r_id , ROW_NUMBER () OVER ( ORDER BY s_date , ROWID ) - ROW_NUMBER () OVER ( PARTITION BY flag ORDER BY s_date , ROWID ) AS grp_id FROM table_name ) SELECT flag , s_date , ROW_NUMBER () OVER ( PARTITION BY flag , grp_id ORDER BY s_date , r_id ) AS d FROM got_grp_id ORDER BY s_date , grp_id , d ;
This assumes that each line can be unique idendified, so that the order is unambiguous. In your sample data, there is completely identical lines, so I used the ROWID to uniquely identify the lines. Using ROWID suppose table_name is a real table, not just a game of results.
I hope that answers your question.
If not, post a small example of data (CREATE TABLE and only relevant columns, INSERT statements) for all of the tables involved and the results desired from these data.
Explain, using specific examples, how you get these results from these data.
Always tell what version of Oracle you are using. -
May result by analytic function that follows
Hi all
I am currently using oracle 10g.
create table
INSERT statementCREATE TABLE fortest ( PROD VARCHAR2(40 BYTE), prodvalues number);
I need the output as followsinsert into fortest values ('dental',10) insert into fortest values ('dental',4) insert into fortest values ('dental',13) insert into fortest values ('dental',3) insert into fortest values ('vision',2) insert into fortest values ('vision',11) insert into fortest values ('vision',33) insert into fortest values ('vision',7)
first column should give me separate prod, prodvalues5 column: should give me the number of similar prod with prodvalues less than 5, same thirdcolumn should have County of similar prod with prodvalues > = 5 and prodvalue < 10 and so on.prod prodvalues <5 prodvalues >=5 and less than 10 prodvalues >=10 dental 2 0 2 vision 1 1 2
Please, not the names of columns of the output tables are just for reference, and I will not use them.
Thanks in advance.Hi Bob,
You don't have to use analytical functions. Here's a solution that doesn't use analytical functions:
with temp as (select prod, case when prodvalues <=5 then 1 else 0 end as prod5, case when prodvalues >=5 and prodvalues <10 then 1 else 0 end as prod5_10, case when prodvalues >= 10 then 1 else 0 end as prod10 from fortest) select prod,sum(prod5) as prod5 , sum(prod5_10) as prod5_10 ,sum(prod10) as prod10 from temp group by prod
-
get a single result with analytical functions
SELECT delrazjn. TYPE, delrazjn. DATE, delrazjn. USER, delrazjn. The IID OF the ZKET_DR delraz, ZKET_DR_JN delrazjn
WHERE delraz. IID = delrazjn. IID
AND (delrazjn. TYPE = 'UP2' GOLD delrazjn. TYPE = 'An increase in 1') AND delrazjn. IID_N IS NOT NULL
This is an example of my sql. But there is more than one result of delrazjn. IID. How can I get the first enterd in DB and ignore others, there will only be one result and no more.
The first result came in, that I can see for delrazjn. DATE.
I try to do that with analytical functions, but without success.You're right, I told you that I can't test the code.
I hope this works now:
SELECT delrazjn.TYPE, delrazjn.DATE, delrazjn.USER, delrazjn.IID FROM ZKET_DR delraz, ZKET_DR_JN delrazjn WHERE delraz.IID = delrazjn.IID AND (delrazjn.TYPE = 'UP2' OR delrazjn.TYPE = 'UP1') AND delrazjn.IID_N IS NOT NULL and delrazjn.date=(select min(d.date) from ZKET_DR_JN d where d.type=delrazjn.type and d.user=delrazjn.user)
-
[8i] can I use an analytical function, or do I need a subquery?
Hi all...
This should be a quick. I hope I can solve my problem with an analytic function, but I don't know if it's possible. Can I use a subquery if I have to, but I'd really rather not.
Here is a very simple version of what I'm trying to do:
I want the results:CREATE TABLE test123 ( field1 VARCHAR2(10) , field2 VARCHAR2(10) , my_date DATE ); INSERT INTO test123 VALUES ('value1', 'a',TO_DATE('12/31/1900','mm/dd/yyyy')); INSERT INTO test123 VALUES ('value1', 'b',TO_DATE('01/02/2010','mm/dd/yyyy')); INSERT INTO test123 VALUES ('value1', 'c',TO_DATE('01/05/2010','mm/dd/yyyy')); INSERT INTO test123 VALUES ('value2', 'a',TO_DATE('12/31/1900','mm/dd/yyyy')); INSERT INTO test123 VALUES ('value2', 'b',TO_DATE('01/01/2010','mm/dd/yyyy')); INSERT INTO test123 VALUES ('value2', 'c',TO_DATE('01/15/2010','mm/dd/yyyy'));
I started with the following query:FIELD1 FIELD2 -------------- value2 a value2 b value2 c value1 a value1 b value1 c
But the problem is the database has a date of 31 December 1900 ' as default / initial for any date field. I don't want these default values taken into account in my calculation of min. I tried to put a WHERE clause in my analytical function [WHERE my_date <>TO_DATE (' 12/31/1900 ',' mm/dd/yyyy')], but I kept getting an error message "missing right parenthesis", so it seems that you can not have a WHERE clause here... or I'm just something wrong?SELECT field1 , field2 FROM test123 ORDER BY MIN(my_date) OVER ( PARTITION BY field1 ) -- removed DESC here , field2
Moreover, it is a 8i database...
Edited by: user11033437 may 20, 2010 17:16: took the 'DESC' criteria out of my order by clause. In my real application, I need DESC, but not the example.Hello
A WHERE clause excludes rows in the results set. Whenever you want you can have a WHERE clause that was more limited (for example, something that would simply exclude MIN calculating values in the ORDER BY clause), then think CASE:
SELECT field1 , field2 FROM test123 ORDER BY MIN ( CASE WHEN my_date > TO_DATE ( '12/31/1900' , 'MM/DD/YYYY' ) THEN my_date END ) OVER (PARTITION BY field1) DESC , field2 ;
This puts the lines for "Value1" first.
The minimum my_date for "Value1" (after excluding the values of 1900) is later than the minimum for "Value2", so I think that you either made a mistake in the desired output, or you do not want sorted by descending order.As always, thanks for the display of the data of the sample and the results so clearly.
Maybe you are looking for
-
White flashing light on my Tower in early 2008
Hi people, I have a Mac Pro 2008 beginning 2.8 Mavericks 10.9.5 running 2xquald. Since the update about a month ago my Mac is acting strange. During the race, fans will ramp up to maximum and keep doing this until I hold the power button to turn of
-
End of 2012 Mac Mini running slow - about to try the following
Hi all The performance of my Mac Mini is trying to drop off and looking for possible solutions to this, I can in this thread: Mac Mini (end 2012) is a little slow. A few months ago I updated to El Capitan, and am now on 10.11.3. Since this update, m
-
How to use a 2nd partition to store data?
The 40 GB HDD on my satellite L10 comes with two 20 GB partitions (C and D drive). I understood (by reading this forum) that it is better to use a partition to store the data. So far, there was no need to use the D drive. But now I need more space. H
-
G50 - 30 - lack of Wifi Realtek Driver for Windows 8.1 on Lenovo G50 - 30
Hi guys, im going to install windows 8.1 on my lenovo g50-30, but thers no Realtek wifi driver for download, only Intel, anyonee has an idea where to find? Mod edit: System model added to the front of the subject line to improve visibility / clarity.
-
Windows Media Player does not recognize the device (iphone)
I'm trying to download music from Windows Media Player on my iphone. I can get the files in the synchronization section but the Media Player does not recognize my device or seem to have a way to connect. Can anyone help?