Help the analytical functions
I have a requirement to get the records of previous values, I used the LEAD feature. The final result should return only rows that have multiple records... If its only one record then that is not part of the result.--Table Creation
CREATE TABLE EHR( ID NUMBER, NAMEID VARCHAR2(100), SAL NUMBER, DT DATE);
-- Inserting the data
Insert into ehr (ID, NAMEID, SAL, DT)
Values (1, 'A', 100, TO_DATE('10/08/2012 12:35:10', 'MM/DD/YYYY HH24:MI:SS'));
Insert into ehr (ID, NAMEID, SAL, DT)
Values (1, 'A', 200, TO_DATE('10/09/2012 12:35:16', 'MM/DD/YYYY HH24:MI:SS'));
Insert into ehr (ID, NAMEID, SAL, DT)
Values (1, 'A', 300, TO_DATE('10/10/2012 12:35:21', 'MM/DD/YYYY HH24:MI:SS'));
Insert into ehr (ID, NAMEID, SAL, DT)
Values (2, 'B', 100, TO_DATE('10/08/2012 12:35:10', 'MM/DD/YYYY HH24:MI:SS'));
Insert into ehr (ID, NAMEID, SAL, DT)
Values (2, 'B', 200, TO_DATE('10/09/2012 12:35:16', 'MM/DD/YYYY HH24:MI:SS'));
Insert into ehr (ID, NAMEID, SAL, DT)
Values (2, 'B', 300, TO_DATE('10/10/2012 12:35:21', 'MM/DD/YYYY HH24:MI:SS'));
Insert into ehr (ID, NAMEID, SAL, DT)
Values (3, 'C', 100, TO_DATE('10/17/2012 09:14:35', 'MM/DD/YYYY HH24:MI:SS'));
COMMIT;
-- Query
select id,nameid, sal, dt, LEAD(sal,1,0) over ( partition by id order by id )as sal_prev,
LEAD(dt) over ( partition by id order by id ) as dt_prev
from ehr
Order by id , DT desc
-- Result
ID NAMEID SAL DT SAL_PREV DT_PREV
1 A 300 10/10/2012 12:35:21 PM 200 10/9/2012 12:35:16 PM
1 A 200 10/9/2012 12:35:16 PM 100 10/8/2012 12:35:10 PM
1 A 100 10/8/2012 12:35:10 PM 0
2 B 300 10/10/2012 12:35:21 PM 200 10/9/2012 12:35:16 PM
2 B 200 10/9/2012 12:35:16 PM 100 10/8/2012 12:35:10 PM
2 B 100 10/8/2012 12:35:10 PM 0
3 C 100 10/17/2012 9:14:35 AM 0
I don't want the ID 3 because it contains only one record of the result above... rest should come. Any ideas?
I think you want to delete the order of numbering and change the select * for columns that you need, if not, it seems, why not test on the sample table you provided?
Edited by: bencol on 17 October 2012 15:05
Edited by: bencol on 17 October 2012 15:08
Tags: Database
Similar Questions
-
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.
-
SQL using the analytic function
Hi allI want a help in the creation of my SQL query to retrieve the data described below:
I have a test of sample table containing data as below:
State ID Desc
MICHAEL 1 T1
ACTIVE 2 T2
T3 3 SUCCESS
DISABLE THE T4 4
The thing I want to do is to select all the lines with an ACTIVE status in the table but is there is no ACTIVE status, my request will give me the last line with MICHAEL status.
I can do this in a single request by using the analytical function for example, if yes can yiu help me on the request of unpacking.
Kind regards
Raluce
Something like that?
I had to fix it.
with testdata until)
Select 1 id, "T1" dsc "DISABLED" status of Union double all the
Select 2 id, 'T2' dsc, the status "ACTIVE" of all the double union
Select id 3, "T3" dsc, the status of 'SUCCESS' of all the double union
Select 4 id, "T4" dsc "DISABLED" status of double
)Select
ID
dsc
status
of testdata
where
status =
-case when (select count (*) in testdata where status = 'ACTIVE') > 0
then 'ACTIVE '.
Another 'DISABLED '.
end
and)
ID in (select id from testdata where status = ' ACTIVE')
or
ID = (select max (id) in testdata when status = 'DISABLED')
)STATE ID DSC
'2' 'T2' 'ACTIVE '.
Maybe it's more efficient
Select
ID
dsc
status
of testdata
where
status =
-case when (select count (*) in testdata where status = 'ACTIVE') > 0
then 'ACTIVE '.
Another 'DISABLED '.
end
and
ID =)
-case when (select count (*) in testdata where status = 'ACTIVE') > 0
then id
on the other
(select max (id) in testdata when status = 'DISABLED')
end
)Post edited by: correction of chris227
Post edited by: chris227
extended -
confusion with the analytical functions
I created an example where I am right now with the help of analytical functions. However, I need the query below to return an additional column. I need to return the result from:-' factor_day_sales * max (sdus)'. Any ideas?
If the first column is located and must have the following results
777777, 5791, 10, 1.5, 15, 90, 135, 7050
the 1350 is the result, I don't know how to do. (some how to multiply factored_day_sales max (sdus) 15 470 = 7050
Thanks for lookingcreate table david_sales ( pro_id number(38), salesidx number (38,6), tim_id number(38)); truncate table david_sales create table david_compensations ( pro_id number(38), tim_id number(38), factor number(38,6)); insert into david_sales values (777777, 10.00, 5795); insert into david_sales values (777777,20.00, 5795); insert into david_sales values (777777, 30.00, 5794); insert into david_sales values (777777, 40.00, 5794); insert into david_sales values (777777, 100.00, 5793); insert into david_sales values (777777, 10.00, 5793); insert into david_sales values (777777,80.00, 5791); insert into david_sales values (777777, 10.00, 5791); insert into david_compensations values (777777, 5795, 1.5); insert into david_compensations values (777777, 5793, 2.0); insert into david_compensations values (777777, 5792, 1.0); insert into david_compensations values (777777, 5791, 1.5); SELECT s.pro_id sales_pro , c.pro_id comp_pro , s.tim_id sales_tim , c.tim_id comp_tim , s.salesidx day_sales , NVL(c.factor, 1) factor , s.salesidx * NVL(c.factor, 1) factored_day_sales , sum(s.salesidx ) over (partition by s.pro_id order by s.pro_id, s.tim_id) Sdus , sum(s.salesidx * NVL(c.factor, 1)) over (partition by s.pro_id order by s.pro_id, s.tim_id) sumMjCj FROM david_sales s , david_compensations c WHERE s.pro_id = c.pro_id(+) AND s.tim_id = c.tim_id(+) AND s.tim_id BETWEEN 5791 AND 5795
Is that what you want?
SELECT s.pro_id sales_pro , c.pro_id comp_pro , s.tim_id sales_tim , c.tim_id comp_tim , s.salesidx day_sales , NVL(c.factor, 1) factor , s.salesidx * NVL(c.factor, 1) factored_day_sales , sum(s.salesidx ) over (partition by s.pro_id order by s.pro_id, s.tim_id) Sdus , sum(s.salesidx * NVL(c.factor, 1)) over (partition by s.pro_id order by s.pro_id, s.tim_id) sumMjCj , (s.salesidx * NVL(c.factor, 1) * sum(s.salesidx ) over (partition by s.pro_id order by s.pro_id, s.tim_id)) FROM david_sales s , david_compensations c WHERE s.pro_id = c.pro_id(+) AND s.tim_id = c.tim_id(+) AND s.tim_id BETWEEN 5791 AND 5795 SALES_PRO COMP_PRO SALES_TIM COMP_TIM DAY_SALES FACTOR FACTORED_DAY_SALES SDUS SUMMJCJ SUMMEDMULTI ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- 777777 777777 5791 5791 80 1.5 120 90 135 10800 777777 777777 5791 5791 10 1.5 15 90 135 1350
I get the 1350
or did you mean:
SELECT s.pro_id sales_pro , c.pro_id comp_pro , s.tim_id sales_tim , c.tim_id comp_tim , s.salesidx day_sales , NVL(c.factor, 1) factor , s.salesidx * NVL(c.factor, 1) factored_day_sales , sum(s.salesidx ) over (partition by s.pro_id order by s.pro_id, s.tim_id) Sdus , sum(s.salesidx * NVL(c.factor, 1)) over (partition by s.pro_id order by s.pro_id, s.tim_id) sumMjCj , s.salesidx * NVL(c.factor, 1) * (sum(s.salesidx * NVL(c.factor, 1)) over (partition by s.pro_id order by s.pro_id, s.tim_id)) summedMulti FROM david_sales s , david_compensations c WHERE s.pro_id = c.pro_id(+) AND s.tim_id = c.tim_id(+) AND s.tim_id BETWEEN 5791 AND 5795 SALES_PRO COMP_PRO SALES_TIM COMP_TIM DAY_SALES FACTOR FACTORED_DAY_SALES SDUS SUMMJCJ SUMMEDMULTI 777777 777777 5795 5795 10 1.5 15 300 470 7050
Note, in the second block, I changed it just to use sumMjCj instead of sDus which seems to correlate with what you wanted (15 * 470 = 7050) while sdus is 15 * 300 = 4500
Published by: tanging on December 11, 2009 06:17
-
Report Builder 6i do not recognize the analytical functions
Hi all, in an attempt to speed up a slow query, I applied the analytical function to it. I can save the query in the generator without any problem, however, I can't create data between this request and other links. After I have comment on the analytical function, data bindings can be made. My colleague says Report Builder 6i is too old so he can recognize only the ANSI SQL syntax. Since our server DB uses Oracle 10 g 2, is there a way for the generator of reports to identify and compile syntax of Oracle 10 g?
Thank you very much.Hello
Your colleague is right. Even if the SQL query is executed by the DB server, reports must analyze the SQL query.
The SQL parser included in reports 6i-based 8.0.6
You can see this version using the report designer:
Menu: Help-> on Report Builder...
ORACLE Server Release 8.0.6.0.0
Concerning
-
Table with 2 columns pro_id, sub_ver_id need only 5 pro_id for each sub_ver_id.
SQL > select * from test1 by SUB_VER_ID;
PRO_ID SUB_VER_ID
---------- ----------
1 0
2 0
3 0
4 0
5 0
6 0
10 1
15 1
16 1
11 1
1 of 12
PRO_ID SUB_VER_ID
---------- ----------
13 1
1 of 14
11 2
3 of 12
.............................
I'm new to the analytical function, I received the request in the form below, but not able to get an idea to limit the SRLNO to only 5 lines for each SUB_VER_ID. Any advice would be much appreciated.
Select distinct sub_ver_id, pro_id, row_number () over (order by sub_ver_id) srlno
from test1 by sub_ver_idCan be as below...
select * from ( select sub_ver_id,pro_id, row_number () over (partition by sub_ver_id order by null) srlno from test1 ) where srlno <=5 order by sub_ver_id
Thank you...
-
A question about the analytical function used with the GROUP BY clause in SHORT
Hi all
I created the following table named myenterprise
If I want to find which is the total sales by city? I'll run the following queryCITY STOREID MONTH_NAME TOTAL_SALES ---------- ---------- ---------- ---------------------- paris id1 January 1000 paris id1 March 7000 paris id1 April 2000 paris id2 November 2000 paris id3 January 5000 london id4 Janaury 3000 london id4 August 6000 london id5 September 500 london id5 November 1000
that works very well and produces the expected result, i.e.SELECT city, SUM(total_sales) AS TOTAL_SALES_PER_CITY FROM myenterprise GROUP BY city ORDER BY city, TOTAL_SALES_PER_CITY;
Now in one of my books SQL (Mastering Oracle SQL) I found another method by using the SUM, but this time as an analytic function. Here's what the method of the book suggests as an alternative to the problem:CITY TOTAL_SALES_PER_CITY ---------- ---------------------- london 10500 paris 17000
I know that the analytic functions are executed after the GROUP BY clause has been transformed completely and Unlike regular aggregate functions, they return their result for each line belonging to the partitions specified in the partition clause (if there is a defined partition clause).SELECT city, SUM(SUM(total_sales)) OVER (PARTITION BY city) AS TOTAL_SALES_PER_CITY FROM myenterprise GROUP BY city ORDER BY city, TOTAL_SALES_PER_CITY;
Now my problem is that I do not understand what we have to use two functions SUM? If we only use one only, i.e.
This generates the following error:SELECT city, SUM(total_sales) OVER (PARTITION BY city) AS TOTAL_SALES_PER_CITY FROM myenterprise GROUP BY city ORDER BY city, TOTAL_SALES_PER_CITY;
The error is generated for the line 2 column 11 which is, for the expression SUM (total_sales), well it's true that total_sales does not appear in the GROUP BY clause, but this should not be a problem, it has been used in an analytical function, so it is evaluated after the GROUP BY clause.Error starting at line 2 in command: SELECT city, SUM(total_sales) OVER (PARTITION BY city) AS TOTAL_SALES_PER_CITY FROM myenterprise GROUP BY city ORDER BY city, TOTAL_SALES_PER_CITY Error at Command Line:2 Column:11 Error report: SQL Error: ORA-00979: not a GROUP BY expression 00979. 00000 - "not a GROUP BY expression" *Cause: *Action:
So here's my question:
Why use SUM (SUM (total_sales)) instead of SUM (total_sales)?
Thanks in advance!
:)
In case you are interested, that's my definition of the table:
Edited by: dariyoosh on April 9, 2009 04:51DROP TABLE myenterprise; CREATE TABLE myenterprise( city VARCHAR2(10), storeid VARCHAR2(10), month_name VARCHAR2(10), total_sales NUMBER); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('paris', 'id1', 'January', 1000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('paris', 'id1', 'March', 7000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('paris', 'id1', 'April', 2000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('paris', 'id2', 'November', 2000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('paris', 'id3', 'January', 5000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('london', 'id4', 'Janaury', 3000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('london', 'id4', 'August', 6000); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('london', 'id5', 'September', 500); INSERT INTO myenterprise(city, storeid, month_name, total_sales) VALUES ('london', 'id5', 'November', 1000);
It is clear that thet Analytics is reduntant here...
You can even use AVG or any analytic function...SQL> SELECT city, 2 avg(SUM(total_sales)) OVER (PARTITION BY city) AS TOTAL_SALES_PER_CITY 3 FROM myenterprise 4 GROUP BY city 5 ORDER BY city, TOTAL_SALES_PER_CITY; CITY TOTAL_SALES_PER_CITY ---------- -------------------- london 10500 paris 17000
-
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.
-
With the help of analytical functions
Hi all
I'm using ODI 11 g (11.1.1.3.0) and I'm doing an interface using analytical functions in the column map, something like below.
Salary on (partition of...)
The problem is that when ODI saw the sum he considers this an aggregate function and the group. Is it possible to understand that it is not an aggregate in ODI function?
I tried to create an option to specify whether it is analytic, then updated IKM with no luck.
< % if (odiRef.getUserExit("ANALYTIC").equals("1")) {% >}
< %} else {% >}
< % = odiRef.getGrpBy (i) % >
< % = odiRef.getHaving (i) % >
< %} % >
Thanks in advanceSeth,
Try this thing posted by Uli:
http://www.business-intelligence-quotient.com/?p=905 -
Help me on the analytic function
Hello
I use oracle version
I have a following tablesSQL> select * From v$version; BANNER ---------------------------------------------------------------- Oracle9i Enterprise Edition Release 9.2.0.8.0 - 64bit Production PL/SQL Release 9.2.0.8.0 - Production CORE 9.2.0.8.0 Production TNS for Solaris: Version 9.2.0.8.0 - Production NLSRTL Version 9.2.0.8.0 - Production
I use following the QUERY for results. Is it possible to get these same results using ANALYTICAL functionsCREATE TABLE emp_info(emp_id number,ename varchar2(10),chk_date date); CREATE TABLE emp_month(emp_id number,emp_month_date date,chk_amt number(10,2)); insert into emp_info VALUES (101,'PAUL',to_date('01-MAR-2009','DD-MON-YYYY')); insert into emp_info VALUES (102,'JOHN',to_date('01-APR-2009','DD-MON-YYYY')); insert into emp_info VALUES (103,'KRIS',to_date('01-MAY-2009','DD-MON-YYYY')); insert into emp_month values (101,'01-DEC-2008',1432); insert into emp_month values (101,'01-JAN-2009',1412); insert into emp_month values (101,'01-FEB-2009',1632); insert into emp_month values (101,'01-MAR-2009',1672); -- insert into emp_month values (102,'01-DEC-2008',2678); insert into emp_month values (102,'01-JAN-2009',2786); insert into emp_month values (102,'01-FEB-2009',2883); insert into emp_month values (102,'01-MAR-2009',2653); insert into emp_month values (102,'01-APR-2009',2653); -- insert into emp_month values (103,'01-NOV-2008',2343); insert into emp_month values (103,'01-DEC-2008',2311); insert into emp_month values (103,'01-JAN-2009',3122); insert into emp_month values (103,'01-FEB-2009',3412); insert into emp_month values (103,'01-MAR-2009',3312); insert into emp_month values (103,'01-APR-2009',3315); insert into emp_month values (103,'01-MAY-2009',4321);
or I would appreciate any solution better than this.Select e.emp_id,e.ename,e.chk_date,sum(chk_amt) year_amt from emp_month em ,(select emp_id,ename,chk_date from emp_info)e where e.emp_id = em.emp_id and em.emp_month_date between trunc(e.chk_date,'YY') AND e.chk_date group by e.emp_id,e.ename,e.chk_date
user12212962 wrote:
I use following the QUERY for results. Is it possible to get these same results using ANALYTICAL functions
or I would appreciate any solution better than this.
I have no idea why you need analytic function. I know: there is no need to view inline in your query:
SQL> Select e.emp_id,e.ename,e.chk_date,sum(chk_amt) year_amt 2 from emp_month em 3 ,(select emp_id,ename,chk_date 4 from emp_info)e 5 where e.emp_id = em.emp_id 6 and em.emp_month_date between trunc(e.chk_date,'YY') AND e.chk_date 7 group by e.emp_id,e.ename,e.chk_date 8 SQL> / EMP_ID ENAME CHK_DATE YEAR_AMT ---------- ---------- --------- ---------- 102 JOHN 01-APR-09 10975 101 PAUL 01-MAR-09 4716 103 KRIS 01-MAY-09 17482 SQL> Select e.emp_id,e.ename,e.chk_date,sum(chk_amt) year_amt 2 from emp_month em, 3 emp_info e 4 where e.emp_id = em.emp_id 5 and em.emp_month_date between trunc(e.chk_date,'YY') AND e.chk_date 6 group by e.emp_id,e.ename,e.chk_date 7 / EMP_ID ENAME CHK_DATE YEAR_AMT ---------- ---------- --------- ---------- 102 JOHN 01-APR-09 10975 101 PAUL 01-MAR-09 4716 103 KRIS 01-MAY-09 17482 SQL>
SY.
-
by using the analytical function to get the right output.
Hello all;
I have the following date of sample below
It's the output I wantcreate table temp_one ( id number(30), placeid varchar2(400), issuedate date, person varchar2(400), failures number(30), primary key(id) ); insert into temp_one values (1, 'NY', to_date('03/04/2011', 'MM/DD/YYYY'), 'John', 3); insert into temp_one values (2, 'NY', to_date('03/03/2011', 'MM/DD/YYYY'), 'Adam', 7); insert into temp_one values (3, 'Mexico', to_date('03/04/2011', 'MM/DD/YYYY'), 'Wendy', 3); insert into temp_one values (4, 'Mexico', to_date('03/14/2011', 'MM/DD/YYYY'), 'Gerry', 3); insert into temp_one values (5, 'Mexico', to_date('03/15/2011', 'MM/DD/YYYY'), 'Zick', 9); insert into temp_one values (6, 'London', to_date('03/16/2011', 'MM/DD/YYYY'), 'Mike', 8);
Any help is appreciated. I'll post my request as soon as I can think of a good logic for this...placeid issueperiod failures NY 02/28/2011 - 03/06/2011 10 Mexico 02/28/2011 - 03/06/2011 3 Mexico 03/14/2011 - 03/20/2011 12 London 03/14/2011 - 03/20/2011 8
Hello
user13328581 wrote:
... Please note, I'm still learning how to use analytical functions.It doesn't matter; analytical functions will not help in this problem. The SUM aggregate function is all you need.
But what do you need to GROUP BY? What is the value of each row of the result will represent? A placeid? Yes, each line will represent only placedid, but it will be divided further. You want a separate line of the output for each placeid and every week, then you'll want of the week and GROUP BY placeid. You don't want to GROUP BY the raw issuedate; that would put on 3 March and 4 March in separate groups. And you don't want to GROUP BY failures; This would mean that a line with 3 failures could never be in the same group in line with 9 failures.This becomes the output you posted from the sample data you posted:
SELECT placeid , TO_CHAR ( TRUNC (issuedate, 'IW') , 'MM/DD/YYYY' ) || ' - '|| TO_CHAR ( TRUNC (issuedate, 'IW') + 6 , 'MM/DD/YYY' ) AS issueperiod , SUM (failures) AS sumfailures FROM temp_one GROUP BY placeid , TRUNC (issuedate, 'IW') ;
You can use a subquery to calculate TRUNC (issuedate, 'IW') once. The code would be of about as complicated, efficiency probably will not improve substantially and the results would be the same.
-
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 ...
-
Oracle 11g Release 2
I'm assuming that the best solution is the use of analytical functions.
create table test3 ( part_type_id varchar2(50) ,group_id number ,part_desc_id number ,part_cmt varchar2(50) ) / insert into test3 values( 'ABC123',1,10,'comment1'); insert into test3 values( 'ABC123',1,10,'comment2'); insert into test3 values( 'ABC123',2,15,'comment1'); insert into test3 values( 'ABC123',2,15,'comment2'); insert into test3 values( 'EFG123',25,75,'comment3'); insert into test3 values( 'EFG123',25,75,'comment4'); insert into test3 values( 'EFG123',25,75,'comment5'); insert into test3 values( 'XYZ123',1,10,'comment6'); insert into test3 values( 'XYZ123',2,15,'comment7'); commit; select * from test3; PART_TYPE_ID GROUP_ID PART_DESC_ID PART_CMT -------------------- ---------- ------------ -------------------- ABC123 1 10 comment1 ABC123 1 10 comment2 ABC123 2 15 comment1 ABC123 2 15 comment2 EDG123 25 75 comment3 EDG123 25 75 comment4 EDG123 25 75 comment5 XYZ123 1 10 comment6 XYZ123 2 15 comment7 9 rows selected. Desired output: PART_TYPE_ID GROUP_ID PART_DESC_ID PART_CMT -------------------- ---------- ------------ -------------------- ABC123 1 10 comment1 ABC123 2 15 comment1 XYZ123 1 10 comment1 XYZ123 2 15 comment2 RULE: where one part_type_id has multiple (2 or more distinct combinations) of group_id/part_desc_id NOTE: There are about 12 columns in the table, for brevity I only included 4.
Post edited by: orclrunner was updated desired output and rule
Hello
Here's one way:
WITH got_d_count AS
(
SELECT part_type_id, group_id, part_desc_id
MIN (part_cmt) AS min_part_cmt
COUNT AS d_count (*) OVER (PARTITION BY part_type_id)
OF test3
GROUP BY part_type_id, group_id, part_desc_id
)
SELECT DISTINCT
group_id, part_desc_id, part_type_id, min_part_cmt
OF got_d_count
WHERE d_count > 1
;
Output:
GROUP_ID PART_DESC_ID MIN_PART_CMT PART_TYPE_ID
------------ ---------- ------------ ------------
ABC123 1 10 comment1
ABC123 2 15 comment1
XYZ123 1 10 comment6
XYZ123 2 15 comment7
Analytical functions, such as the COUNTY and MIN, many global versions, in addition, it can give the same results. Use the analytical versions when each row of output corresponds to exactly 1 row of input and the aggregate and GROUP BY version when each line of output corresponds to a group of lines 1 or more input. In this issue, each line of output appears to be a group of input lines having the same group_id, part_type_id, and part_desc_id (I'm guessing just, this only has never stated), so I used GROUP BY to get 1 row of output for every input lines.
-
How to define the condition in the analytic function
Oracle 10g version
Hi all
I have the following data samples:
Examples of data
WITH DATA AS
(
SELECT 100 case_id, next_date, to_date('01-feb-2015','dd-mon-yyyy') UNION double, ALL crt_date to_date('01-jan-2015','dd-mon-yyyy')
SELECT 100 case_id, next_date, to_date('01-mar-2015','dd-mon-yyyy') UNION double, ALL crt_date to_date('01-feb-2015','dd-mon-yyyy')
SELECT 100 case_id, next_date, to_date('01-apr-2015','dd-mon-yyyy') UNION double, ALL crt_date to_date('01-may-2015','dd-mon-yyyy')
SELECT 100 case_id, to_date('01-jun-2015','dd-mon-yyyy') next_date, to_date('01-apr-2015','dd-mon-yyyy') crt_date FROM dual
)
SELECT wagneur, MIN (next_date) OVER (PARTITION BY case_id) min_dt_analytical
,(
SELECT MIN (next_date) DATA dd
WHERE dd.case_id = d.case_id
AND dd.next_date > crt_date
) min_dt_sub_query
DATA d
;
My question is that I get min_dt_sub_query using sub query but I want to use the analytical instead of query sub function so I created min_dt_analytical column, but I do not have how to give the condition that is AND dd.next_date > crt_date analytical so that I can get the same result as min_dt_sub_query data accordingly. Thanks in advance
Concerning
MIT
Do not know if I understood your needs... but... something like that?
WITH DATA AS (SELECT 100 case_id, next_date, to_date('01-feb-2015','dd-mon-yyyy') UNION double, ALL crt_date to_date('01-jan-2015','dd-mon-yyyy')
SELECT the 100 case_id, next_date, to_date('01-mar-2015','dd-mon-yyyy') UNION double, ALL crt_date to_date('01-feb-2015','dd-mon-yyyy')
SELECT the 100 case_id, next_date, to_date('01-apr-2015','dd-mon-yyyy') UNION double, ALL crt_date to_date('01-may-2015','dd-mon-yyyy')
SELECT 100 case_id, next_date, to_date('01-apr-2015','dd-mon-yyyy') double crt_date to_date('01-jun-2015','dd-mon-yyyy'))
SELECT d.
MIN (next_date) OVER (PARTITION BY case_id) min_dt_analytical
MIN(CASE WHEN next_date > crt_date THEN next_date ELSE NULL END) OVER (PARTITION BY case_id) AS min_dt_sub_query2
DATA d;
HTH
-
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
Maybe you are looking for
-
Hello I add to change the settings of an account email (server name has changed) and mail flows always to and from the account. But all mail in the IMAP folder is no longer displayed in Thunderbird just mail that came in since the change. How to rest
-
How to connect Qosmio F10 with a VCR to record a VHS on DVD?
Hello I have a problem with the VCR and the Qosmio.The problem is that the software (a software I tried) may not recognize the video recorder. There are also has two entries in Qosmio, which one is right (S-video or video-D). What should I do?
-
Droid Maxx (Kitkat) - car dock Griffin (Dialer)
Hey guys,. Today, I write about my current business with Motorola. This is the case number is140121-006278. I use my car griffin dock to make and receive calls on my Maxx Droid while I'm on the road. I noticed since the update of Kitkat on my Droid M
-
"Computer" shows the memory network card. When you try to open it, I get the following error message... Location is not availableY:\ is not accessible.The handle is not valid. If I right click the icon and select 'Properties', then the properties of
-
Can u explain someone on table mutation error pls...
Can u explain someone on table mutation error pls...