clarification of analytical FIRST_VALUE function
How Sal is calculated in the query below. first_value will fetch the first value in a window of.
For deptno = 10 we have 3 files so why is filling for all records of deptno = 2450 10.I was clear with output if I use the command by sal after partition by deptno but under output query is not clear.
clarification of the request:
Select empno, deptno, first_value (sal) on sal (deptno partition)
WCP
o/p:
deptno, EmpNo, sal
7782 | 10 | 2450 |
7934 | 10 | 2450 |
7839 | 10 | 2450 |
7902 | 20 | 3000 |
7788 | 20 | 3000 |
7566 | 20 | 3000 |
7369 | 20 | 3000 |
7876 | 20 | 3000 |
7521 | 30 | 1250 |
7654 | 30 | 1250 |
7844 | 30 | 1250 |
7900 | 30 | 1250 |
7499 | 30 | 1250 |
7698 | 30 | 1250 |
the EMP data:
Select * from emp;
7782 | CLARK | MANAGER | 7839 | JUNE 9, 81 | 2450 | 10 | |
7934 | MILLER | CLERK | 7782 | JANUARY 23, 82 | 1300 | 10 | |
7839 | KING | PRESIDENT | NOVEMBER 17, 81 | 5000 | 10 | ||
7902 | FORD | ANALYST | 7566 | DECEMBER 3, 81 | 3000 | 20 | |
7788 | SCOTT | ANALYST | 7566 | APRIL 19, 87 | 3000 | 20 | |
7566 | JONES | MANAGER | 7839 | 2 APRIL 81 | 2975 | 20 | |
7369 | SMITH | CLERK | 7902 | DECEMBER 17, 80 | 800 | 20 | |
7876 | ADAMS | CLERK | 7788 | MAY 23, 87 | 1100 | 20 | |
7521 | WARD | SELLER | 7698 | FEBRUARY 22, 81 | 1250 | 500 | 30 |
7654 | MARTIN | SELLER | 7698 | 28 SEP-81 | 1250 | 1400 | 30 |
7844 | TURNER | SELLER | 7698 | 08 SEP-81 | 1500 | 0 | 30 |
7900 | JAMES | CLERK | 7698 | DECEMBER 3, 81 | 950 | 30 | |
7499 | ALLEN | SELLER | 7698 | FEBRUARY 20, 81 | 1600 | 300 | 30 |
7698 | BLAKE | MANAGER | 7839 | MAY 1, 81 | 2850 | 30 |
If you do not specify a COMMAND BY ADOPTERAIS function FIRST_VALUE returns then a deterministic in.
Tags: Database
Similar Questions
-
assign the number to a line based on the analytical condition function
Oracle 11g Server
ID val1 val2 1 0 0a 1 1 0 b 1 2 0c 2 0 0a 2 2 0 b WITH input AS (SELECT 1 id ,0 val1 ,'0a' val2 FROM dual UNION ALL SELECT 1 id ,1 val1 ,'0b' val2 FROM dual UNION ALL SELECT 1 id ,2 val1 ,'0c' val2 FROM dual UNION ALL SELECT 2 id ,0 val1 ,'0a' val2 FROM dual UNION ALL SELECT 2 Id ,2val1 ,'0b' val2 FROM dual) SELECT * FROM input;
!-[CodeBlockEnd:ae52826b-04c5-4aa4-a6c0-1d0405656e55]-->Output:
ID val1 val2 assigned_number 1 0 0a 0 1 1 0 b 0 1 2 0c 2 2 0 0a 0 2 2 0 b 1 The dense numbering sequence must be assigned to each line based on the column id and val1.
For an identifier given, the numbering begins only after val1 > 1 until then the assigned_number will be zero.
WITH the entry INTO
(SELECT 1 id)
0 val1
'0' has val2
OF the double
UNION ALL
SELECT 1 id
1 val1
b '0' val2
OF the double
UNION ALL
SELECT 1 id
2 val1
, 0'c ' val2
OF the double
UNION ALL
SELECT 2 id
0 val1
'0' has val2
OF the double
UNION ALL
SELECT the Id 2
2val1
b '0' val2
THE DOUBLE)
SELECT id, val1, val2,
Rank() over (partition by order of case when val1 > 1 then 0 otherwise end val1) dr-1
SINCE the entry;
ID VAL1 IS DR
---------- ---------- -- ----------
1 0 0a 0
1 1 0b 0
1 2 0c 2
2 0 0a 0
2 2 0b 1
-
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.67The 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).
-
I am trying to determine the differences between the use of the function analytic first_value vs using the analytical function of the DENSE_RANK FIRST OVER() style.
In particular, when is it appropriate to use one against the other? In truth the DENSE_RANK OVER() FIRST seems to be a much more flexible version of the first_value function.
All illumination is very appreciated.Hello
Claytonian wrote:
To clarify,There is not difference between the analytical FIRST_VALUE function, the FIRST analytical function and it comes down to coding preference/maintainability?
I just guess that there is no performance difference. I saw not all studies or experiments to back up.
The only difference between value FIRST and FIRST_VALUE analytic functions is how you call them. You were very careful to mention that you're talking about analytic functions. Ok.
There is a big difference between the FIRST and FIRST_VALUE value of aggregate functions: the FIRST aggregate function exists, but there is no aggregate FIRST_VALUE function. If you want to see the x that is associated with the lowest y in an aggregate query, use FIRST. -
Numbering of the lines based on two columns
Hello world
I´d would like to know if there is a way to achieve the numbering shown in the second table below indicating only Oracle native functions, like ROW_COUNT() on the partition, etc.
I m using Oracle 10 g.
The logic used is:
From 1, increment one each time that the ORIGIN is identical to the FIRST ORIGIN of the line (ID) group.
In order to compare the ORIGIN of each line with the FIRST ORIGIN of the group, I used the function LAG to create a column that will be the FIRST ORIGIN of the value in the group.ID ORIGIN DESTINATION ORDER ------------------------------------ 1 A B 1 1 B A 2 1 A B 3 1 B C 4 1 C A 5 ID ORIGIN DESTINATION ORDER NUMBERING -------------------------------------------------- 1 A B 1 1 1 B A 2 1 1 A B 3 2 1 B C 4 2 1 C A 5 2
However, I was not able to number the lines as shown above (column NUMBERING).
Any help will be much appreciated.
--------------------------------------------------------------------------------------------------------------
Test query:WITH T AS ( SELECT 1 ID, 'A' ORIGIN, 'B' DESTINATION, 1 ORDERING FROM DUAL UNION ALL SELECT 1 ID, 'B' ORIGIN, 'A' DESTINATION, 2 ORDERING FROM DUAL UNION ALL SELECT 1 ID, 'A' ORIGIN, 'B' DESTINATION, 3 ORDERING FROM DUAL UNION ALL SELECT 1 ID, 'B' ORIGIN, 'C' DESTINATION, 4 ORDERING FROM DUAL UNION ALL SELECT 1 ID, 'C' ORIGIN, 'A' DESTINATION, 5 ORDERING FROM DUAL ) SELECT T.ID , T.ORIGIN , T.DESTINATION , T.ORDERING , LAG (T.ORIGIN, T.ORDERING -1, 0) OVER (PARTITION BY T.ID ORDER BY T.ID , T.ORDERING) FIRST_ORIGIN_OF_GROUP FROM T ORDER BY T.ID , T.ORDERING
Hello
Here's one way:
WITH got_first_origin AS ( SELECT id, origin, destination, ordering , FIRST_VALUE (origin) OVER ( PARTITION BY id ORDER BY ordering ) AS first_origin FROM t ) SELECT id, origin, destination, ordering , COUNT ( CASE WHEN origin = first_origin THEN 1 END ) OVER ( PARTITION BY id ORDER BY ordering ) AS numbering FROM got_first_origin ;
This assumes that the combination of id and order is unique. Within an id, you place your order does not have to be consecutive integers, or something like that.
Analytical functions cannot be nested (the argument of the function of COUNTY anlytic can not call the analytical FIRST_VALUE function); The subquery is necessary.
You could do something with a LAG, as you have tried, rather than FIRST_VALUE, but you would still need a subquery, for the same reason. -
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)
-
Need help with the analytic function
I want to get the highest employee details and the 2nd highest employee for a particular service. But also the Department should have more than 1 employee.
I tried the query and it gave me the correct results. But I wonder if there is another solution than to use the subquery.
Here is the table and the query result:
with t as ( select 1 emp_id,3 mgr_id,'Rajesh' emp_name,3999 salary,677 bonus,'HR' dpt_nme from dual union select 2 ,3 ,'Gangz',4500,800,'Finance' from dual union select 3 ,4 ,'Sid',8000,12000,'IT' from dual union select 4 ,null,'Ram',5000,677,'HR' from dual union select 5 ,4,'Shyam',6000,677,'IT' from dual union select 6 ,4 ,'Ravi',9000,12000,'IT' from dual ) select * from (select emp_id, mgr_id, emp_name, dpt_nme, salary, row_number() over (partition by dpt_nme order by salary desc) rn from t where dpt_nme in (select dpt_nme from t group by dpt_nme having count(*) > 1)) where rn < 3
Hello
You need a subquery, but you don't need more than that.
Here's a way to eliminate the additional subquery:WITH got_analytics AS ( SELECT emp_id, mgr_id, emp_name, dpt_nme, salary , ROW_NUMBER () OVER ( PARTITION BY dpt_nme ORDER BY salary DESC ) AS rn , COUNT (*) OVER ( PARTITION BY dpt_nme ) AS dpt_cnt FROM t ) SELECT emp_id, mgr_id, emp_name, dpt_nme, salary , rn FROM got_analytics WHERE rn < 3 AND dpt_cnt > 1 ;
Analytical functions are calculated after the clause WHERE is applied. Since we need to use the results of the analytical ROW_NUMBER function in a WHERE clause, which means that we have to calculate ROW_NUMBER in a subquery and use the results in the WHERE clause of the main query. We can call the COUNT function analytical in the same auxiliary request and use the results in the same WHERE clause of the main query.
Would what results you if there is a link for the 2nd highest salary in some Department? For example, if you add this line to your sample data:
select 7 ,3 ,'Sunil',8000,12000,'IT' from dual union
? You can use RANK rather than ROW_NUMBER.
-
Analytic function can support this requirement?
As a result of some Qry, I get the following result set. Column1 Column2 A 100 A 200 A 200 A 100 B 200 B 200 B 200 C 100 C 200 D 200 D 200 E 200 With this as input i had to take some decision like, For a particular Column1 value, if all the avaiable value of column2 is 200 (B, D & E in this case), i need to do one set of operations, if atleast one of the value for Column2 is non 200 (A & C in this case), i need to do another set of operation. How to frame the If clause or any other approach? By using Analytical count(*) function, is it possible to generate something like Column1 Column2 Column3(200_count) A 100 2 A 200 2 A 200 2 A 100 2 B 200 3 B 200 3 B 200 3 C 100 1 C 200 1 D 200 3 D 200 3 E 200 3
Jin
Something lilke this?with data as ( select 'A' column1, 100 column2 from dual union all select 'A' column1, 200 from dual union all select 'A' column1, 200 from dual union all select 'A' column1, 100 from dual union all select 'B' column1, 200 from dual union all select 'B' column1, 200 from dual union all select 'B' column1, 200 from dual union all select 'C' column1, 100 from dual union all select 'C' column1, 200 from dual union all select 'D' column1, 200 from dual union all select 'D' column1, 200 from dual union all select 'E' column1, 200 from dual ) select column1,column2,count(0) over (partition by column1,column2) cnt from data order by column1
The query above is considered the occuerence for each Column1 Column2.
If you want to count only 200 something like can help you.with data as ( select 'A' column1, 100 column2 from dual union all select 'A' column1, 200 from dual union all select 'A' column1, 200 from dual union all select 'A' column1, 100 from dual union all select 'B' column1, 200 from dual union all select 'B' column1, 200 from dual union all select 'B' column1, 200 from dual union all select 'C' column1, 100 from dual union all select 'C' column1, 200 from dual union all select 'D' column1, 200 from dual union all select 'D' column1, 200 from dual union all select 'E' column1, 200 from dual ) select column1,column2,sum( case when column2=200 then 1 else 0 end ) over (partition by column1) cnt from data order by column1
Kind regards
BobinPublished by: Buga added second query
-
A job for the analytical function "PARTION OF?
Hello
I'm still a little fuzzy on the use of partitions, but this looks like a possible candidate for me.
I need to count the number of different customers who visit an office in one day. If a customer visits an office more than once in a single day that counts for 1.
Entry
OFFICE CLIENT TRAN_DATE
1-11-1 April 09
1-11-1 April 09
1-11-1 April 09
1 11 2 April 09
2 22 2 April 09
2 22 2 April 09
2 33 2 April 09
Select a.office as 'OFFICE', a.customer AS 'CUSTOMER', a.tran_date AS 'TRAN_DATE', COUNT (*)
Of
(SELECT 1 AS 'OFFICE', AS A 'CUSTOMER' 11, APRIL 1, 2009 "AS"TRAN_DATE"OF THE DOUBLE
UNION ALL
SELECT 1, 11, APRIL 1, 2009 "OF THE DOUBLE
UNION ALL
SELECT 1, 11, APRIL 1, 2009 "OF THE DOUBLE
UNION ALL
SELECT 1: 11, 2 APRIL 2009 "OF THE DOUBLE
UNION ALL
SELECT 2: 22, APRIL 2, 2009 "OF THE DOUBLE
UNION ALL
SELECT 2: 22, APRIL 2, 2009 "OF THE DOUBLE
UNION ALL
SELECT 2: 33, APRIL 2, 2009 "OF THE DOUBLE
) one;
Desired result
1 1 April 09 1
1-2 April 09 1
2 2 April 09 2
Is this possible with partitions, do I have to use subqueries, or some other methid?
Thanks in advance for your help,
Lou
Published by: wind in the face on April 15, 2009 13:34Hey, Lou,
PARTITION BY is not a function.
COUNT is a function. There is an aggregate COUNT function and also an analytical function of COUNTY. (Almost all aggregate functions have analytical counterparts).How can you tell if a function is used as an aggregate function or Analytics? The analytic form will be "OVER (
)" after his altercation; the overall shape will not be.
PARTITION BY is one of the elements that may form part of the analytical clause.
"PARTITION BY x, y ' in an analuytic function corresponds to" GROUP BY x, y "when using functions aggreggate.You can get the same results for a large number of problems using either global or analytical of a function versions.
For example, both versions global and analytical County can tell you that vistied office only 1 customer 1 April 1, but 2 clients visited the office 2 April 2.
If you use the aggregation function ACCOUNT and ' GROUP BY Office, tran_date ', as John suggested, you will get only one line for each distinct combination of office and tran_date. In other words, even if there are 3 rows of your table where office = 1 and tran_date = April 1, the result set will have onely a row where office = 1 and tran_date = 1 April.
Because it is exactly what you want, you can use the aggregate COUNT fucntion, as shown in John.If you use the analytical ACCOUNT function, there will be a line of output for each row in your table.
So with the sample data you posted, this query:SELECT office , tran_date , COUNT (DISTINCT customer) OVER ( PARTITION BY office , tran_date ) AS cnt FROM table_x;
will these results:
. OFFICE TRAN_DATE CNT ---------- ----------- ---------- 1 01-APR-2009 1 1 01-APR-2009 1 1 01-APR-2009 1 1 02-APR-2009 1 2 02-APR-2009 2 2 02-APR-2009 2 2 02-APR-2009 2
To get the exact results you want, you can use SELECT DISTINCT, like this:
SELECT DISTINCT office , COUNT (DISTINCT customer) OVER ...
-
Hi all
I have a table which includes
ID, first_name, last name and date of birth
I want to retrieve all the records that have the same name and DOB
for example.
ID, first_name, last name, DOB
1 xyz abc 01/01/2012
hij 2 efg 15/05/2012
3 xyz abc 01/01/2012
4 xyz abc 01/01/2012
so in the output of 1, 3 and 4 rows will appear only.
can someone advise please on the appropriate SQL function
Thanks in advance
Hello
One way is to use the analytical COUNT function:
WITH got_num_rows AS
(
SELECT id, first_name, last_name, dob
, COUNT (*) OVER (PARTITION BY first name
last_name
, dob
) AS num_rows
FROM table_x
)
SELECT id, first_name, last_name, dob
OF got_num_rows
WHERE num_rows > 1
;
The subquery is needed here, because the analytical functions are calculated after the WHERE clause has been applied. To use the results of an anlytic function in a WHERE clause, you must calculate the function in a subquery, then you can use the results where you want (including the WHERE clause) of a Super query.
-
ITS POSSIBLE TO CALL A FUNCTION WHEN THE LINES ARE ALREADY MET?
Hello, I'm new in pl sql and I learn.
My requirment is:
I made a function for calculating the values of cumulative of the account period.
My problem is:
I have this data
amount of the account
12 100
12 50
13 200
and I have this simple query
SELECT flat, account, acumulated_amount (period)
THE F1
GROUP account, the period
I get
amount of the account
12 150
13 200
I want to add is to add a column that is calculated by a function. This function calculates the cumulative amount of previous years of account.
If I insert this select statement so that it will calculate the cumulative amount each online account and what I want is show the amount acumullated after the grouped data
For example: my accumulated amount of the 12 is 1000 and based on my request I will receive
account amount acumullated
12 150 2000
13 200
because the cumulative amount in each line and I need perform the calculation only when data are collected. Something like this:
account amount acumullated
12-150-1000
13 200
Someone has an idea how to do this?
Thanks in advance
Paulo DuarteHi, Paulo,
user4256563 wrote:
Hello, I'm new in pl sql and I learn.
My requirment is:I made a function for calculating the values of cumulative of the account period.
My problem is:
I have this data
amount of the account
12 100
12 50
13 200Whenever you have a problem, please psot of CREATE TABLE and INSERT statements for your sample data, even if it's only 3 rows.
Always say what version of Oracle you are using (for example, 11.2.0.1.0).and I have this simple query
SELECT flat, account, acumulated_amount (period)
THE F1
GROUP account, the periodI get
amount of the account
12 150
13 200You have 3 columns in your SELECT statement, but only 2 columns in the output. Is one of the output NULL columns?
I want to add is to add a column that is calculated by a function. This function calculates the cumulative amount of previous years of account.
If I insert this select statement so that it will calculate the cumulative amount each online account and what I want is show the amount acumullated after the grouped dataFor example: my accumulated amount of the 12 is 1000 and based on my request I will receive
account amount acumullated
12 150 2000
13 200Sorry, I don't see how you get 1000 or 2000 for examples of data that you said that you have. Can you explain, step by step, how to get this figure?
because the cumulative amount in each line and I need perform the calculation only when data are collected. Something like this:
account amount acumullated
12-150-1000
13 200That's what you want, or you want the results given just before her, with accumulated = 2000?
Whatever it is, I still don't see how you get 1000 or 2000 of 100, 50 and 200.Someone has an idea how to do this?
Analytical functions can do what you want. When you use analytical functions and aggregation in the same query, the GROUP BY clause is applied and aggregate functions are calculated before the analytical functions are started.
You can write (or analytical) global functions defined by the user. For a simple (and very useful) example, called STRAGG, see
http://asktom.Oracle.com/pls/asktom/f?p=100:11:0:P11_QUESTION_ID:2196162600402 -
using the function min() inside the instruction box
I have a problem with the following select statement
Select
patient_id
, sum (case when ch.cancer_site_id in ('3', ' 39 ', ' 12') and min (ch.diagnosis_age) < 40 0' then '1' other ' end) in breast cancer
Of...
Patient_id group
I get an error "not a single group group function.
The main table, that I work with is so implemented.
PatientID | diagnosis_age | cancer_site_id
12345678 | 35. 4
12345678 | 40. 4
12345678 | 42. 12
12345678 | 34. 31
87654321 | 50. 12
cancer_site_ids 4 and 31 must get grouped together and called breast cancer. cancer_site_id 12 (and others) is cancer of the colon.
Finally I need the output to look like this
PatientID | min (breast_diagnosis_age) < 40 | min (breast_diagnosis_age) > 40 | min (colon_diagnosis_age) > 40
-------------------------------------------------------------------------------
12345678 | 1. 0 | 1
87654321 | 0 | 0 | 1
My final request is much more complicated than that, but it's the last part that I can't understand.Hello
Welcome to the forum!
You can use the analytic MIN function to get the earlier diagnosis_age.
Analytical functions are calculated after aggregation functions. If you use the aggregate functions to rotate the data, this means that you need to calculate the minimum age in a subquery and do all aggregates in the main query.
I mean, it is something like this:WITH got_min_diagnosis_age AS ( SELECT patiendid , MIN (diagnosis_age) OVER ( PARTITION BY CASE WHEN cancer_site IN (4, 31) THEN 'breast' WHEN cancer_site IN (3, 12, 39) THEN 'colon' END ) AS diagnosis_age , CASE WHEN cancer_site IN (4, 31) THEN 'breast' WHEN cancer_site IN (3, 12, 39) THEN 'colon' END AS type FROM table_x ) SELECT patientid , COUNT ( CASE WHEN type = 'breast' AND min_diagnosis_age <= 40 THEN 1 END ) AS breast_up_to_40_cnt , COUNT ( CASE WHEN type = 'breast' AND min_diagnosis_age > 40 THEN 1 END ) AS breast_over_40_cnt , COUNT ( CASE WHEN type = 'colon' AND min_diagnosis_age > 40 THEN 1 END ) AS colon_over_40_cnt FROM got_min_diagnosis_age GROUP BY patientid ORDER BY patientid ;
You can also calculate type in a subquery, then use it to calculate the min_diagnosis_age for the type in a second subquery. If the expression to get type is much more complicated in reality that it is in this small sample, which can be better.
Published by: Frank Kulash, November 3, 2010 15:00
You have a cancer_site table, that is, a table that has one line for each valid value of cancer_site (3, 4, 12,...)?
If so, you need to add a column to this table to indicate what kind of cancer, each site is associated. You could join this table in the subquery, rather than using CASE expressions. The fact that 4 of the site is associated with breast cancer is the type of information that belongs to a table, not hardcoded in a query.
If you do not have a cancer_siote table, thus creating one can be a good idea. -
[8i] help with function with parameters (for the calculation of the work)
Let me start by saying, I've never written a function before, and I do not have access to create a feature in my database (that is, I can't test this feature). I am trying to achieve a function I can ask my IT Department to add for me. I hope that someone can take a look at what I wrote and tell me if this should work or not, and if it's the right way to go to solve my problem.
I'm creating a function to make a very simple calculation of work (add/subtract a number of days to a date in the calendar).
The database, I work with has a table with the schedule of work. Here is a sample table and sample data, representative of what is in my work table calendar:
The table includes since 01/01/1980 but 31/12/2015.CREATE TABLE caln ( clndr_dt DATE, shop_days NUMBER(5) CONSTRAINT caln_pk PRIMARY KEY (clndr_dt) ); INSERT INTO caln VALUES (To_Date('01/01/1980','mm/dd/yyyy'),0); INSERT INTO caln VALUES (To_Date('01/02/1980','mm/dd/yyyy'),1); INSERT INTO caln VALUES (To_Date('01/03/1980','mm/dd/yyyy'),2); INSERT INTO caln VALUES (To_Date('01/04/1980','mm/dd/yyyy'),3); INSERT INTO caln VALUES (To_Date('01/05/1980','mm/dd/yyyy'),3); INSERT INTO caln VALUES (To_Date('01/06/1980','mm/dd/yyyy'),3); INSERT INTO caln VALUES (To_Date('01/07/1980','mm/dd/yyyy'),4); INSERT INTO caln VALUES (To_Date('01/08/1980','mm/dd/yyyy'),5); INSERT INTO caln VALUES (To_Date('01/09/1980','mm/dd/yyyy'),6); INSERT INTO caln VALUES (To_Date('01/10/1980','mm/dd/yyyy'),7); INSERT INTO caln VALUES (To_Date('01/11/1980','mm/dd/yyyy'),8); INSERT INTO caln VALUES (To_Date('01/12/1980','mm/dd/yyyy'),8); INSERT INTO caln VALUES (To_Date('01/13/1980','mm/dd/yyyy'),8); INSERT INTO caln VALUES (To_Date('01/14/1980','mm/dd/yyyy'),9);
I have written (and validated) this parameter query that performs the calculation of my working day (mday):
Based on this request, I created the following function (and I have no idea if it works or if the syntax is right, etc..):SELECT cal.clndr_dt FROM CALN cal , ( SELECT cal.shop_days+:mdays AS new_shop_days FROM CALN cal WHERE cal.clndr_dt =:start_date ) a WHERE cal.shop_days = a.new_shop_days AND ROWNUM =1 ORDER BY cal.clndr_dt;
I'm also not sure how to do to have the function handle results that would return a date outside the range of dates that appear in the table (prior to 01/01/1980 or after until 31/12/2015 - or, another way to look at what was, before the caln.clndr_dt or the caln.clndr_dt MAX value MIN value).CREATE OR REPLACE FUNCTION add_mdays (start_date IN DATE, mdays IN NUMBER(5)) RETURN DATE IS new_date DATE; BEGIN SELECT cal.clndr_dt FROM CALN cal , ( SELECT cal.shop_days+mdays AS new_shop_days FROM CALN cal WHERE cal.clndr_dt =start_date ) a WHERE cal.shop_days = a.new_shop_days AND ROWNUM =1 ORDER BY cal.clndr_dt; RETURN new_date; END add_mdays; //edit 9:31 AM - noticed I left off this bit
My goal is to be able to use the function in a situation similar to the following:
First of all, here is a sample table and data:
And here's how I would use my function:CREATE TABLE orders ( ord_no NUMBER(5), plan_start_dt DATE, CONSTRAINT orders_pk PRIMARY KEY (ord_no) ); INSERT INTO orders VALUES (1,To_Date('01/08/1980','mm/dd/yyyy')); INSERT INTO orders VALUES (2,To_Date('01/09/1980','mm/dd/yyyy')); INSERT INTO orders VALUES (3,To_Date('01/10/1980','mm/dd/yyyy'));
Thus, the function would allow me to come back, for each command in my table of orders, the date is 3 days working (mdays) before the start of the plan of each order.SELECT orders.ord_no , orders.plan_start_dt , add_mdays(orders.plan_start_dt, -3) AS prep_date FROM orders
I go about it the right way? I have to create a function to do this, or is there a way for me to integrate my request (which makes my mday calculation) in the example query above (eliminating the need to create a function)?
Thank you very much in advance!
Published by: user11033437 on February 2, 2010 08:55
Fixed some typos in the last insert statements
Published by: user11033437 on February 2, 2010 09:31 (fixed some syntax in the function)Hello
Ah, referring to Oracle 8 and is not not able to test your own code makes me nostalgic for the good old days, when you have entered your cards and led to a window to the computer center and waited an hour for the work to be performed and then seen printing to find that you had made a typo.
If you write functions, you should really test yourself. Like all codes, functions forge be written small not: write a line or two (or sometimes just a part of what would later become a single line), test, make sure it is running properly and repeat.
Ideally, your employer must create a pattern of development in a development database that you can use.
You can legally download your own instance of Oracle Express Edition free; just be careful not to use features that are not available in the database where the code will be deployed.You need a function to get the desired results:
SELECT o.ord_no , o.plan_start_dt , MIN (e.clndr_dt) AS prep_date FROM orders o , caln l , caln e WHERE l.clndr_dt = o.plan_start_dt AND e.shop_days = l.shop_days - 3 GROUP BY o.ord_no , o.plan_start_dt ;
It would be more effective (and somewhat simpler) If you've added a column (let's call it work_day) identified whether each line represents a work_day or not.
For each value of shop_days, exactly 1 row will be considered as a working day.
Then, the query may be something like:SELECT o.ord_no , o.plan_start_dt , e.clndr_dt AS prep_date FROM orders o , caln l , caln e WHERE l.clndr_dt = o.plan_start_dt AND e.shop_days = l.shop_days - 3 AND e.work_day = 1 ;
You can use the analytic LAG function to populate the work_day column.
A function would certainly be useful, although perhaps slower.
The function you have posted has some errors:
an argument can be stated under NUMBER (5); Just NUMBER.
(b) when you SELECT in PL/SQL, as you do, you must SELECT a variable to store the results.
(c) ROWNUM is arbitrary (making it useless in this problem) unless you draw a neat subquery. I don't think you can use ORDER BY in subqueries in Oracle 8. Use the ROW_NUMBER analytic function.
(d) the service must end with an END statement.Given your current caln table, here's how I would write the function:
CREATE OR REPLACE FUNCTION add_mdays ( start_date IN DATE DEFAULT SYSDATE, mdays IN NUMBER DEFAULT 1 ) RETURN DATE DETERMINISTIC IS -- add_mdays returns the DATE that is mdays working days -- after start_date. (If mdays < 0, the DATE returned -- will be before start_date). -- Work days do not include Saturdays, Sundays or holidays -- as indicated in the caln table. new_date DATE; -- to be returned BEGIN SELECT MIN (t.clndr_dt) INTO new_date FROM caln f -- f stands for "from" , caln t -- t stands for "to" WHERE f.clndr_dt = TRUNC (start_date) AND t.shop_days = f.shop_days + TRUNC (mdays) ; RETURN new_date; END add_mdays; / SHOW ERRORS
Production code forge be robust (which includes "fool-proofing").
Try to anticipate what people errors might appeal to your function and correct for them where possible.
For example, if it only makes sense for start_date at midnight, mdays to be an integer, use TRUNC in the function where soembody passes a good value.
Allow default arguments.
Comment of your function. Put all comments within the service (i.e. after CREATION and before the END) so that they will remain in the data dictionary.
If, given the same arguments, the function always returns the same value, mark it as DETERMINISTIC, for efficiency. This means that the system will remember the values transmitted rather than to call the function whenever it is said to.I wish I could score questions such as 'Correct' or 'useful '; you get 10 points for sure.
You posted CREATE TABLE and INSERT statements (without even be begged).
You gave a clear description of the problem, including the expected results.
The code is well formatted and easy to read.
All around, one of the more thoughtful and well written questions I've seen.
Play well! Keep up the good work!Published by: Frank Kulash, February 2, 2010 13:10
Added to my own version of the function. -
What makes this deterministic query?
copy paste everything here, from oradoc. It's a short read. "The following example shows how the
FIRST_VALUE
function deterministic by ordering on a unique key.' '.Orders only complementary criteria is:
order of salary desc, hire_date
vs
salary desc order (other examples).
Basically could someone please explain to me how the last example of query/is deterministic.
Goal
FIRST_VALUE
is an analytic function. It returns the first value in an ordered set of values. If the first value of the game is null, the function returnsNULL
unless you specifyIGNORE NULLS
. This setting is useful for data densification. If you specifyIGNORE NULLS
, thenFIRST_VALUE
returns non-null of punch in the game, orNULL
If all values are null. See "using partitioned outer joins: examples ' for an example of data densification.You cannot nest analytic functions using
FIRST_VALUE
or any other analytic function forexpr
. However, you can use other built-in function expressionsexpr
. Refer to "about the SQL Expressions" for more information about the valid forms ofexpr
.For each employee in the Department 90, the following example selects the name of the employee with the lowest wages.
The example illustrates the nondeterministic nature of the
FIRST_VALUE
function. Kochhar and DeHaan have the same salary, are stowed adjacent. Kochhar appears first because the rows returned by the subquery are ordered byemployee_id
. However, if the rows returned by the subquery are sorted byemployee_id
by descending order, as in the following example, the function then returns a different value:The following example shows how the
FIRST_VALUE
function deterministic by ordering on a unique key.Hello
I agree with your first reaction: looks like a bad example for me, too. In the hr.employees table, the combination [wages, hire_date] lies be unique, so, you place your order by the two columns only arrives to give consistent results. As long as no 2 employees have both the same pay and same hire_date, the query will produce the same results. But I wouldn't say that deterministic unless there was a constraint to ensure that the combination is necessarily unique. It would have been better if they had used employee_id (which is unique) instead of the hire_date as the tiebreaker.
-
Presentation of the results help
I came across a weird result when you use the analytical LAST_VALUE function which did not work as expected. I install a simple test and it is not yet worked as I expect:
create the table first_test (col1, col2, col3 date number number);
Insert Into first_test VALUES(1,100,'01-Jan-11');
Insert Into first_test VALUES(1,101,'02-Jan-11');
Insert Into first_test VALUES(1,100,'03-Jan-11');
Insert Into first_test VALUES(2,100,'01-Jan-11');
Insert Into first_test VALUES(2,101,'02-Jan-11');
Insert Into first_test VALUES(2,100,'03-Jan-11');
I then run the following query:
SELECT col1,
col2,
col3,
LAST_VALUE (col2) OVER (PARTITION BY col1 ORDER BY col3) as test
OF first_test;
All the documentation, I find, I expect that the value of the "test" column would be 100 for each record, because it should partition by col1, col3 control and then get the last value in the ordered list (100). My results look like this:
"COL1", "COL2", "COL3" 'TEST '.
1 100 1 JANUARY 11 100
1 101 2 JANUARY 11 101
1 100 100 3 JANUARY 11
2 100 1 JANUARY 11 100
2 101 2 JANUARY 11 101
2 100 100 3 JANUARY 11
I've also tested this using the FIRST_VALUE function:
SELECT col1,
col2,
col3,
FIRST_VALUE (col2) OVER (PARTITION BY col1 ORDER BY col3) as test
OF first_test;
"COL1", "COL2", "COL3" 'TEST '.
1 100 1 JANUARY 11 100
1 101 2 JANUARY 11 100
1 100 100 3 JANUARY 11
2 100 1 JANUARY 11 100
2 101 2 JANUARY 11 100
2 100 100 3 JANUARY 11
It is the result that I expect that the first value in the sorted list is 100. My DB is Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64 bit.
Did I miss something in the way it should work?Hello
Welcome to the forum!
It's a very intuitive feature LAST_VALUE.
The best way to get the desired results is to use the FIRST_VALUE order and descending, like this:SELECT col1, col2, col3, FIRST_VALUE (col2) OVER ( PARTITION BY col1 ORDER BY col3 DESC ) AS test FROM first_test;
The reason why LAST_VALUE didn't work as expected is to the windowing clause (or lack thereof). With any analytic function, when you use an ORDER BY clause, you can also specify a window clause, using the keyword LINE or LINES. If you do not specify a window clause, then the default value is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. So, if you use the default windowing clause, LAST_VALUE means the last until and including the current line , then, indeed, LAST_VALUE (col2) is just the same as col2.
With the help of FIRST_VALUE, the default windowing clause works the way you want.To get the results you want using LAST_VALUE, you must explicitly give a windowing clause, like this:
SELECT col1, col2, col3, LAST_VALUE (col2) OVER ( PARTITION BY col1 ORDER BY col3 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) AS test FROM first_test;
Published by: Frank Kulash, August 18, 2011 15:43
Additional explanation
Maybe you are looking for
-
How to reset the counter of DAQ
I have a system such as X coordinates and Y and in moving my counter will increase, but when the system arrives in the precise coordinates, it must reset the counter (equal zero) that this will be the zero point.Attached is a picture to show how I re
-
I think that my nephew has attempted to change the user account profiles to get into blocked websites. Any ideas?
-
Windows 8 WMP 12 no sorting or the renaming of new songs
As noted above, new songs, I add to the library does not get renamed, or sorted in a folder. All the checkboxes in the options are set correctly. I have ran the store, rebuilt the library repeatedly and in vain. What to do to get this working?
-
Cannot install Ubuntu 12.04.3 server in Vmware Workstation 10
Hi allDoes not work when I try to install Ubuntu on It. It starts normally asking for a language,then when I click on "Install Ubuntu server" my screen goes black and nothing happens.It will never select it your localized language and to install.Same
-
I bought the Adobe Acrobat Standard XI and is unable to complete the download because I already downloanded Acrobat XI pro trial.