Home » SQL & PL/SQL » SQL & PL/SQL » Complex query (merged) (10g)
Complex query (merged) [message #644237] Sun, 01 November 2015 06:06 Go to next message
m.abdulhaq
Messages: 254
Registered: April 2013
Location: Ajman
Senior Member
I want to create absent report for employees , i have two tables in this regards , one is master and the other is transaction , the transaction detail tables stores the record of people who are comming on daily basis , but there is no record stored any where to show if he is absent.What i did to get this output , i am using cartesian product between emp_trans and a view generating number of days in month , to find out which employee the record is missing .Is there a better way to do this as if i model this query on actual data of employee which has more than 2000 rows , the query will hang.




CREATE  TABLE emp
(
  empno     NUMBER(4),
  ename     VARCHAR2(10 BYTE),
  hiredate  DATE
  );


  INSERT INTO EMP(EMPNO,ENAME,HIREDATE) VALUES (1,'JOHN',TO_DATE('01/10/2015','DD/MM/RRRR'));
  
  INSERT INTO EMP(EMPNO,ENAME,HIREDATE) VALUES (2,'JACK',TO_DATE('01/10/2015','DD/MM/RRRR'));

 create table emp_trans 
  (
  emp_no     NUMBER(4),
  emp_dt     DATE,
  hrs        number(8,2));

  INSERT INTO EMP_TRANS(EMP_NO,EMP_DT,HRS) VALUES (1,TO_DATE('01/11/2015','DD/MM/RRRR'),8)
  
  INSERT INTO EMP_TRANS(EMP_NO,EMP_DT,HRS) VALUES (1,TO_DATE('02/11/2015','DD/MM/RRRR'),8)
  
  INSERT INTO EMP_TRANS(EMP_NO,EMP_DT,HRS) VALUES (2,TO_DATE('02/11/2015','DD/MM/RRRR'),8)



CREATE OR REPLACE VIEW gen_month_dt
AS
   SELECT     TRUNC (SYSDATE, 'MM') + LEVEL - 1 dt
         FROM DUAL
   CONNECT BY LEVEL <= CAST (TO_CHAR (LAST_DAY (SYSDATE), 'dd') AS INT)
     ORDER BY 1




select empno,dt,nvl((SELECT NVL(HRS,0) FROM EMP_TRANS
WHERE EMP_NO = emp.empno AND EMP_DT = dt),0) hrs
 from gen_month_dt,emp ;

EMPNO,DT,HRS
1,11/1/2015,8
2,11/1/2015,0
1,11/2/2015,8
2,11/2/2015,8
1,11/3/2015,0
2,11/3/2015,0
1,11/4/2015,0
2,11/4/2015,0
1,11/5/2015,0
2,11/5/2015,0
1,11/6/2015,0
2,11/6/2015,0
1,11/7/2015,0
2,11/7/2015,0
1,11/8/2015,0
2,11/8/2015,0
1,11/9/2015,0
2,11/9/2015,0
1,11/10/2015,0
2,11/10/2015,0
1,11/11/2015,0
2,11/11/2015,0
1,11/12/2015,0
2,11/12/2015,0
1,11/13/2015,0
2,11/13/2015,0
1,11/14/2015,0
2,11/14/2015,0
1,11/15/2015,0
2,11/15/2015,0
1,11/16/2015,0
2,11/16/2015,0
1,11/17/2015,0
2,11/17/2015,0
1,11/18/2015,0
2,11/18/2015,0
1,11/19/2015,0
2,11/19/2015,0
1,11/20/2015,0
2,11/20/2015,0
1,11/21/2015,0
2,11/21/2015,0
1,11/22/2015,0
2,11/22/2015,0
1,11/23/2015,0
2,11/23/2015,0
1,11/24/2015,0
2,11/24/2015,0
1,11/25/2015,0
2,11/25/2015,0
1,11/26/2015,0
2,11/26/2015,0
1,11/27/2015,0
2,11/27/2015,0
1,11/28/2015,0
2,11/28/2015,0
1,11/29/2015,0
2,11/29/2015,0
1,11/30/2015,0
2,11/30/2015,0


 SELECT EMPno,count(dt) from (
select empno,dt,(nvl((SELECT NVL(HRS,0) FROM EMP_TRANS
WHERE EMP_NO = emp.empno AND EMP_DT = dt),0)) hrs
 from gen_month_dt,emp )
 where nvl(hrs,0)=0 
 GROUP BY EMPNO


EMPNO,COUNT(DT)
1,28
2,29










Re: Complex query [message #644239 is a reply to message #644237] Sun, 01 November 2015 06:22 Go to previous messageGo to next message
Michel Cadot
Messages: 68647
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

1/ Use PARTTION BY empno
2/ See Join for the OUTER JOIN to get the result you want to get.

Re: Complex query [message #644252 is a reply to message #644239] Mon, 02 November 2015 00:57 Go to previous messageGo to next message
m.abdulhaq
Messages: 254
Registered: April 2013
Location: Ajman
Senior Member
thanks michael, you meant something like this below.In that case we need to filter out more.


SELECT emp_no, emp_dt,dt, ROW_NUMBER () OVER (PARTITION BY emp_no ORDER BY dt) rn
  FROM emp_trans, gen_month_dt
 WHERE emp_dt(+) = dt
 order by emp_no,dt


EMP_NO,EMP_DT,DT,RN
1,11/1/2015,11/1/2015,1
1,11/2/2015,11/2/2015,2
2,11/2/2015,11/2/2015,1
,,11/3/2015,1
,,11/4/2015,2
,,11/5/2015,3
,,11/6/2015,4
,,11/7/2015,5
,,11/8/2015,6
,,11/9/2015,7
,,11/10/2015,8
,,11/11/2015,9
,,11/12/2015,10
,,11/13/2015,11
,,11/14/2015,12
,,11/15/2015,13
,,11/16/2015,14
,,11/17/2015,15
,,11/18/2015,16
,,11/19/2015,17
,,11/20/2015,18
,,11/21/2015,19
,,11/22/2015,20
,,11/23/2015,21
,,11/24/2015,22
,,11/25/2015,23
,,11/26/2015,24
,,11/27/2015,25
,,11/28/2015,26
,,11/29/2015,27
,,11/30/2015,28

Re: Complex query [message #644254 is a reply to message #644252] Mon, 02 November 2015 01:27 Go to previous messageGo to next message
Michel Cadot
Messages: 68647
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

No I meant outer_join_clause, see query_partition_clause.

Re: Complex query [message #644261 is a reply to message #644254] Mon, 02 November 2015 03:11 Go to previous messageGo to next message
Michel Cadot
Messages: 68647
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator
SQL> with
  2    cal as (
  3      select trunc(sysdate,'MONTH')+level-1 dt
  4      from dual
  5      connect by level <= extract(day from last_day(sysdate))
  6    )
  7  select e.emp_no, count(c.dt) nb
  8  from cal c
  9       left outer join
 10       emp_trans e partition by (emp_no)
 11       on e.emp_dt = c.dt
 12  where e.emp_dt is null
 13  group by e.emp_no
 14  order by e.emp_no
 15  /
    EMP_NO         NB
---------- ----------
         1         28
         2         29

[Updated on: Mon, 02 November 2015 03:12]

Report message to a moderator

Re: Complex query [message #644284 is a reply to message #644261] Mon, 02 November 2015 09:22 Go to previous messageGo to next message
m.abdulhaq
Messages: 254
Registered: April 2013
Location: Ajman
Senior Member
thanks michael,i did it using partition and right out join, sorry for the delay in posting.


select emp_n,count(missing_dt) from (
SELECT t.emp_no emp_n,x.dt,nvl(t.emp_dt,TO_DATE('01/01/1990')) missing_dt
  FROM emp_trans t  partition by (emp_no)
right outer join
    ( select dt from gen_month_dt  ) x
    on (t.emp_dt = x.dt) 
 )      where missing_dt = TO_DATE('01/01/1990')
        group by emp_n



EMP_N,COUNT(MISSING_DT)
1,28
2,29





icon14.gif  Re: Complex query [message #644297 is a reply to message #644261] Mon, 02 November 2015 22:31 Go to previous messageGo to next message
m.abdulhaq
Messages: 254
Registered: April 2013
Location: Ajman
Senior Member
thanks Michael, it was great learning something new "Partition Outer Join" , Performance wise also its very much better than using Cartesian.
Re: Complex query [message #644326 is a reply to message #644284] Tue, 03 November 2015 04:55 Go to previous messageGo to next message
sandeep_orafaq
Messages: 88
Registered: September 2014
Member
m.abdulhaq wrote on Mon, 02 November 2015 09:22
thanks michael,i did it using partition and right out join, sorry for the delay in posting.


select emp_n,count(missing_dt) from (
SELECT t.emp_no emp_n,x.dt,nvl(t.emp_dt,TO_DATE('01/01/1990')) missing_dt
  FROM emp_trans t  partition by (emp_no)
right outer join
    ( select dt from gen_month_dt  ) x
    on (t.emp_dt = x.dt) 
 )      where missing_dt = TO_DATE('01/01/1990')
        group by emp_n



EMP_N,COUNT(MISSING_DT)
1,28
2,29







One should always use format while converting string to date. Just a suggestion. It might work for your session but could create issue in another session where NLS_DATE_FORMAT is different from your expectation.
Re: Complex query [message #644349 is a reply to message #644326] Tue, 03 November 2015 11:39 Go to previous message
m.abdulhaq
Messages: 254
Registered: April 2013
Location: Ajman
Senior Member
thanks sandeep.
Previous Topic: stored procedure to Inserting new rows and updating existing rows
Next Topic: Nested table as a out parameter in procedure
Goto Forum:
  


Current Time: Fri Apr 26 13:40:44 CDT 2024