(select count(*) from table) > 0 then [message #661680] |
Mon, 27 March 2017 21:43 |
|
ecca
Messages: 9 Registered: March 2017
|
Junior Member |
|
|
Hi,
For your info, I'm currently working on a script to count consecutive working days. The script works fine on TOAD but somehow it triggered Encountered the symbol "SELECT" error every time when I tried to compile it in Form Builder 11g.
I have read the suggestion to store the result into a variable using select into but somehow I didn't quite understand how to fix the error.
Any feedback will be much appreciated. Thanks
select floor(sysdate-max(dt)) workingDays
from(
select distinct dt,
(case when (select count(*)
from leave_staff_trx where date_trx = t1.dt and staff_no = '1024') > 0
then 1 else 0 end) cnt
from(select trunc(sysdate) as DT from dual
union
SELECT TRUNC (SYSDATE-rownum) dt FROM DUAL CONNECT BY ROWNUM < 30) t1
order by 1 desc) x1
where cnt =0;
|
|
|
Re: (select count(*) from table) > 0 then [message #661682 is a reply to message #661680] |
Tue, 28 March 2017 00:31 |
|
Michel Cadot
Messages: 68729 Registered: March 2007 Location: Saint-Maur, France, https...
|
Senior Member Account Moderator |
|
|
Welcome to the forum.
Please read OraFAQ Forum Guide and How to use [code] tags and make your code easier to read.
Format your SQL, If you don't know how to do it, learn it using SQL Formatter and here's the result:
SELECT Floor(SYSDATE - Max(dt)) workingDays
FROM (SELECT DISTINCT dt,
( CASE
WHEN (SELECT Count(*)
FROM leave_staff_trx
WHERE date_trx = t1.dt
AND staff_no = '1024') > 0 THEN 1
ELSE 0
END ) cnt
FROM (SELECT Trunc(SYSDATE) AS DT
FROM dual
UNION
SELECT Trunc (SYSDATE - ROWNUM) dt
FROM dual
CONNECT BY ROWNUM < 30) t1
ORDER BY 1 DESC) x1
WHERE cnt = 0;
Easier to read, isn't it?
Try this way:
with
t1 as ( SELECT Trunc(SYSDATE) AS DT
FROM dual
UNION
SELECT Trunc (SYSDATE - ROWNUM) dt
FROM dual
CONNECT BY ROWNUM < 30
),
cnt ( SELECT t1.dt, nvl2(Count(*),1,0) cnt
FROM t1 left outer join leave_staff_trx on date_trx = t1.dt
WHERE staff_no = '1024'
group by t1.dt
)
SELECT Floor(SYSDATE - Max(dt)) workingDays
from cnt
WHERE cnt = 0
Note: I just try to fix your error but didn't try to understand your query which may be functionally wrong.
Note:
1/ DISTINCT and ORDER BY are useless, just a waste of resources
2/ cnt always returns the same dates than dt and the following always returns 0:
SQL> with
2 t1 as ( SELECT Trunc(SYSDATE) AS DT
3 FROM dual
4 UNION
5 SELECT Trunc (SYSDATE - ROWNUM) dt
6 FROM dual
7 CONNECT BY ROWNUM < 30
8 )
9 SELECT Floor(SYSDATE - Max(dt)) workingDays
10 from t1
11 /
WORKINGDAYS
-----------
0
So this query is equivalent to:
select 0 workingDays
from dual
where not exists ( select null from leave_staff_trx
where staff_no = '1024'
and date_trx >= trunc(sysdate-30)
What is the question your query wants to answer?
[Updated on: Tue, 28 March 2017 02:07] Report message to a moderator
|
|
|
|
|
|
|
|
Re: (select count(*) from table) > 0 then [message #661710 is a reply to message #661705] |
Wed, 29 March 2017 01:26 |
|
Michel Cadot
Messages: 68729 Registered: March 2007 Location: Saint-Maur, France, https...
|
Senior Member Account Moderator |
|
|
SQL> select floor(sysdate-max(dt)) workingDays
2 from(
3 select distinct dt,
4 (case when (select count(*) from leave_staff_trax where date_trx = t1.dt and badge = '201414') > 0 then 1 else 0 end) cnt
5 from(select trunc(sysdate) as DT from dual union SELECT TRUNC (SYSDATE-rownum) dt FROM DUAL CONNECT BY ROWNUM < 30) t1
6 order by 1 desc) x1
7 where cnt =0;
WORKINGDAYS
-----------
4
should be
SQL> SELECT Floor(SYSDATE - Max(dt)) workingDays
2 FROM (SELECT DISTINCT dt,
3 ( CASE
4 WHEN (SELECT Count(*)
5 FROM leave_staff_trax
6 WHERE date_trx = t1.dt
7 AND badge = 201414) > 0 THEN 1
8 ELSE 0
9 END ) cnt
10 FROM (SELECT Trunc(SYSDATE) AS DT
11 FROM dual
12 UNION
13 SELECT Trunc (SYSDATE - ROWNUM) dt
14 FROM dual
15 CONNECT BY ROWNUM < 30) t1
16 ORDER BY 1 DESC) x1
17 WHERE cnt = 0
18 /
WORKINGDAYS
-----------
4
Slightly modifying my first query to be more efficient, it works:
SQL> with
2 t1 as ( SELECT Trunc(SYSDATE) AS DT
3 FROM dual
4 UNION
5 SELECT Trunc (SYSDATE - ROWNUM) dt
6 FROM dual
7 CONNECT BY ROWNUM < 30
8 ),
9 cnt as ( SELECT t1.dt, Count(date_trx) cnt
10 FROM t1 left outer join
11 ( select * from LEAVE_STAFF_TRAX where badge = 201414 )
12 on date_trx = t1.dt
13 group by t1.dt order by t1.dt
14 )
15 SELECT Floor(SYSDATE - Max(dt)) workingDays
16 from cnt
17 WHERE cnt = 0
18 /
WORKINGDAYS
-----------
4
The following should be more efficient:
SQL> with
2 data as (
3 select BADGE, DATE_TRX,
4 lead(DATE_TRX) over (partition by BADGE order by DATE_TRX desc) prev_date,
5 max(DATE_TRX) over (partition by badge) last_day
6 from LEAVE_STAFF_TRAX
7 where DATE_TRX >= trunc(sysdate-30)
8 )
9 select badge,
10 case when last_day = trunc(sysdate) then trunc(sysdate)-max(date_trx)+1
11 else 0
12 end workingDays
13 from data
14 where prev_date != date_trx-1
15 group by badge, last_day
16 order by badge
17 /
BADGE WORKINGDAYS
---------- -----------
39496 0
40386 0
201414 4
470346 2
543789 3
Or, for only one badge:
SQL> with
2 data as (
3 select BADGE, DATE_TRX,
4 lead(DATE_TRX) over (order by DATE_TRX desc) prev_date,
5 max(DATE_TRX) over () last_day
6 from LEAVE_STAFF_TRAX
7 where badge = 201414 and DATE_TRX >= trunc(sysdate-30)
8 )
9 select case when last_day = trunc(sysdate) then trunc(sysdate)-max(date_trx)+1
10 else 0
11 end workingDays
12 from data
13 where prev_date != date_trx-1
14 group by last_day
15 /
WORKINGDAYS
-----------
4
Note: do not enclose your number between quotes you will invalidate index use.
[Edit: add limit of 30 days]
[Updated on: Wed, 29 March 2017 01:52] Report message to a moderator
|
|
|
|
|
|
|
|
|
|
|
Re: (select count(*) from table) > 0 then [message #661762 is a reply to message #661761] |
Fri, 31 March 2017 01:36 |
|
Littlefoot
Messages: 21823 Registered: June 2005 Location: Croatia, Europe
|
Senior Member Account Moderator |
|
|
I'm glad you solved it.
One more objection: it is the KEY-NEXT-ITEM you use. Consider switching to WHEN-VALIDATE-ITEM trigger. KEY-NEXT-ITEM was used in old, character-mode Forms versions (such as 3.0). For backward compatibility, it is still here. However, it wouldn't fire if user navigates out of that item using any other option (such as mouse click, <Next block> key, and similar).
|
|
|