ORA-00923 : plsql Arithmetic operator and INTO - oracle

This sql code is running fine
SELECT
primax-stdmax ,
stdmax-stdmaxapp
FROM
(SELECT MAX(sequence#) stdmax, thread#, resetlogs_change#
FROM v$archived_log
WHERE standby_dest='YES'
GROUP BY thread#, resetlogs_change#) a,
(SELECT MAX(sequence#) stdmaxapp, thread#, resetlogs_change#
FROM v$archived_log
WHERE standby_dest='YES'
AND applied='YES'
GROUP BY thread#, resetlogs_change#) b,
(SELECT MAX(sequence#) primax, thread#, resetlogs_change#
FROM v$archived_log
WHERE standby_dest='NO'
GROUP BY thread#, resetlogs_change#) c
WHERE a.thread# = b.thread#
AND b.thread# = c.thread#;
But when I convert into pl/sql code as below , its failing.
declare
l_shipgap NUMBER := 0;
l_applygap NUMBER := 0;
begin
SELECT
primax-stdmax into l_shipgap,
stdmax-stdmaxapp into l_applygap
FROM
(SELECT MAX(sequence#) stdmax, thread#, resetlogs_change#
FROM v$archived_log
WHERE standby_dest='YES'
GROUP BY thread#, resetlogs_change#) a,
(SELECT MAX(sequence#) stdmaxapp, thread#, resetlogs_change#
FROM v$archived_log
WHERE standby_dest='YES'
AND applied='YES'
GROUP BY thread#, resetlogs_change#) b,
(SELECT MAX(sequence#) primax, thread#, resetlogs_change#
FROM v$archived_log
WHERE standby_dest='NO'
GROUP BY thread#, resetlogs_change#) c
WHERE a.thread# = b.thread#
AND b.thread# = c.thread#;
end;
/
Execution :
Error:
SQL> #aa.sql
stdmax-stdmaxapp into l_applygap
*
ERROR at line 7:
ORA-06550: line 7, column 20:
PL/SQL: ORA-00923: FROM keyword not found where expected
ORA-06550: line 5, column 1:
PL/SQL: SQL Statement ignored

Wrong syntax.
As a statement contains one SELECT, one FROM, one WHERE clause, the same goes for INTO - only one:
SELECT
primax - stdmax,
stdmax - stdmaxapp
INTO l_shipgap, l_applygap
FROM ...
(with "one", I'm not talking about subqueries - just like you have, but the general SELECT statement syntax).

Related

How to add results of two select commands in same query and from same table - Oracle SQL

I have this query that works fine:
SELECT
RE.IDREUNIONFALLA as "IdReunion",
NVL((select count(1) as pozos
from REUNION_FALLAPREMATURA
where IDREUNIONFALLA=RE.IDREUNIONFALLA
group by IDREUNIONFALLA),0) as "PlanificadosFallas",
NVL((select count(1) as pozos
from REUNION_FALLAPOZOS_AD
where IDREUNIONFALLA=RE.IDREUNIONFALLA
group by IDREUNIONFALLA),0) as "PlanificadosPozos"
FROM REUNIONFALLA RE
This query returns multiple rows with two columns, each of them with a int number, like this:
What i need to do, is to get the SUM from each row, in a new column. You can see what i mean on the next image:
I already thit this:
SELECT
NVL((SELECT count(1) as pozos
from REUNION_FALLAPREMATURA
where IDREUNIONFALLA=RE.IDREUNIONFALLA
group by IDREUNIONFALLA),0) as "PlanificadosFallas",
NVL((SELECT count(1) as pozos
from REUNION_FALLAPOZOS_AD
where IDREUNIONFALLA=RE.IDREUNIONFALLA
group by IDREUNIONFALLA),0) as "PlanificadosPozos",
NVL((SELECT SUM(fallas) PlanificadosTotal
FROM -- i add this five lines
(
select count(1) as fallas
from REUNION_FALLAPREMATURA
where IDREUNIONFALLA=RE.IDREUNIONFALLA
group by IDREUNIONFALLA
UNION ALL
select count(1) as fallas
from REUNION_FALLAPOZOS_AD
where IDREUNIONFALLA=RE.IDREUNIONFALLA
group by IDREUNIONFALLA
)),0) as "Total"
FROM REUNIONFALLA RE
but i get this next error:
ORA-00904: "RE"."IDREUNIONFALLA": invalid identifier
is there a solution for this?
[edit]
This one is cleaner :
SELECT
RE.IDREUNIONFALLA as "IdReunion",
NVL(t1.pozos,0) as "PlanificadosFallas",
NVL(t2.pozos,0) as "PlanificadosPozos",
(NVL(t1.pozos,0)s + NVL(t2.pozos,0)) AS "Total"
FROM REUNIONFALLA RE
LEFT JOIN (
select IDREUNIONFALLA, count(1) as pozos
from REUNION_FALLAPREMATURA
group by IDREUNIONFALLA
) t1
ON t1.IDREUNIONFALLA = RE.IDREUNIONFALLA
LEFT JOIN (
select IDREUNIONFALLA, count(1) as pozos
from REUNION_FALLAPOZOS_AD
group by IDREUNIONFALLA
) t2
ON t2.IDREUNIONFALLA=RE.IDREUNIONFALLA
As you can see, you make the count a single time and not for each line : should run faster if you have a big number of line.
This should do it :
SELECT
t1.IdReunion,
t1.PlanificadosFallas,
t1.PlanificadosPozos,
(t1.PlanificadosFallas + t1.PlanificadosPozos) AS "Total"
FROM (
SELECT
RE.IDREUNIONFALLA as "IdReunion",
NVL((select count(1) as pozos from REUNION_FALLAPREMATURA where IDREUNIONFALLA=RE.IDREUNIONFALLA group by IDREUNIONFALLA),0) as "PlanificadosFallas",
NVL((select count(1) as pozos from REUNION_FALLAPOZOS_AD where IDREUNIONFALLA=RE.IDREUNIONFALLA group by IDREUNIONFALLA),0) as "PlanificadosPozos"
FROM REUNIONFALLA RE
) AS t1

using MAX function in HQL

The below query has some issues. The subquery that I use here runs without any errors when run separately. However if I run the whole query below it ends in error.
"Error while compiling statement: FAILED: ParseException line 13:30 cannot recognize input near 'select' 'max' '(' in expression specification"
select acct_num from table1
where ind = 'Y'
and b = (select max(yr_mth_num) from table2)
and st_dt = (select cast(max(st_dt) as date) from table2)
Try this:
SELECT T1.acct_num
FROM table1 T1
LEFT SEMI JOIN
(SELECT
max(yr_mth_num) as max_yr_mth_num,
cast(max(st_dt) as date) as max_st_dt
FROM table2) T2
ON T1.b = T2.max_yr_mth_num
AND T1.st_dt = T2.max_st_dt
AND T1.ind = 'Y'

Oracle sql derived table - optional aliasing

I came across a client's query yesterday, it is something like:
select count(*) as countall,
person,
location
from (select custid,
min("Date") as theDate,
person,
data.location
from data join
customer on customer.customerid = custid
where status = 1
and custid <> -1
group by custid,
person,
data.location) --[NO ALIAS]
group by person,location
I don't have a lot of hours in Oracle, but in MS SQL this would not fly, to my knowledge. Any time I have used a derived table it throws an error, so to encounter scenarios such as this piques my interest. I couldn't find anything to explain it on the interwebs, hopefully somebody can explain the scenarios where aliasing for derived tables is optional and when it is not.
You only need to alias, when you are referencing a column that is not uniquely defined. This means that the column exists in more than one table/derived table. A reference could be in the select statement, or a join. If all columns are unique, then you do not need an alias.
I prefer to alias all of the time for clarity, and because it helps with Intellisense in PL/SQL.
--ALIAS needed, because the 'a' column referenced is not unique
--this will throw an error
select a, a, b, c
from (select 'A1' as a, 'B1' as b, 'C1' as c from dual),
(select 'A2' as a from dual);
--this will not throw an error
select t1.a, t2.a, b,c
from (select 'A1' as a, 'B1' as b, 'C1' as c from dual) t1,
(select 'A2' as a from dual) t2;
;
--ALIAS not needed for join, because all referenced columns are unique
select a, b, c, d, e, f
from (select 'A' as a, 'B' as b, 'C' as c from dual)
join (select 'D' as d, 'E' as e, 'F' as f from dual)
on a = d;
--ALIAS needed for join, because the 'x' column referenced is not unique
--this will throw an error
select a
from (select 'A' as a, 'B' as b, 'C' as c, 'X' as x from dual)
join (select 'D' as d, 'E' as e, 'F' as f, 'X' as x from dual)
on x = x;
--this will not throw an error
select a
from (select 'A' as a, 'B' as b, 'C' as c, 'X' as x from dual) t1
join (select 'D' as d, 'E' as e, 'F' as f, 'X' as x from dual) t2
on t1.x = t2.x;
In this instance, you are selecting all columns from your subquery and hence the subquery was written with no alias .
If you were to join this subquery with another table or perhaps another subquery, you would want to alias so that you can reference the join columns using the defined alias.

Oracle SQL Left and right outer Join with/Without where clause giving different outputs

Why is there a difference in output for the below queries?
As per my understanding it should give the same output for the first 3 queries and same output for the last 3 queries.
select count(*)
from CTM_People a left outer join user_x b
on a.remedy_login_id = b.login_name;
Result 1: 152771
select count(*)
from CTM_People a left outer join user_x b
on a.remedy_login_id = b.login_name
where a.remedy_login_id like '%';
Result 2: 151185
select count(*)
from CTM_People a left outer join user_x b
on a.remedy_login_id = b.login_name and a.remedy_login_id like '%';
Result 3: 152771
select count(*)
from CTM_People a right outer join user_x b
on a.remedy_login_id = b.login_name;
Result 1: 150899
select count(*)
from CTM_People a right outer join user_x b
on a.remedy_login_id = b.login_name where a.remedy_login_id like '%';
Result 2: 150889
select count(*)
from CTM_People a right outer join user_x b
on a.remedy_login_id = b.login_name and a.remedy_login_id like '%';
Result 3: 150899
Total count in both the tables are
select count(*) from CTM_People; **Result : 152771**
select count(*) from user_x; **Result : 150899**
LIKE operator doesn't accept NULLs. Please check a.remedy_login_id

loop based on query result get error

I have the result of a first query, and then based on that result I want to join with other tables so I can select the fields in the query result and other tables.
I construct the following
BEGIN
FOR a_rec in (select col1, min(col2) as col2,col3 from a_tbl group by (col1, col3))
LOOP
select a_rec.col2, d_tbl.col4
from b_tbl b, c_tbl c, d_tbl d
where b.col1 = a_rec.col1 and c.col5 = b.col5 and d.col6 = c.col6;
END LOOP;
END;
then it reminds me that PLS-00428: an INTO clause is expected in this SELECT statement, so I create a temp table and the code becomes:
BEGIN
FOR a_rec in (select col1, min(col2) as col2,col3 from a_tbl group by (col1, col3))
LOOP
select a_rec.col2, d_tbl.col4 into tmp_tbl
from b_tbl b, c_tbl c, d_tbl d
where b.col1 = a_rec.col1 and c.col5 = b.col5 and d.col6 = c.col6;
END LOOP;
END;
then I get error like this PLS-00403: expression 'TMP_TBL' cannot be used as an INTO-target of a SELECT/FETCH statement
Maybe I should put the first query result into a temp table and then join it with other tables, although I wonder whether I can do it in such a procedure?
A SELECT INTO throws an error if the SELECT statement returns anything other than a single row. So that's clearly not what you want here. Since tmp_tbl is a global temporary table, you could do an INSERT SELECT in your loop
BEGIN
FOR a_rec in (select col1, min(col2) as col2,col3
from a_tbl
group by (col1, col3))
LOOP
INSERT INTO tmp_tbl( col2, col4 )
select a_rec.col2, d_tbl.col4
from b_tbl b,
c_tbl c,
d_tbl d
where b.col1 = a_rec.col1
and c.col5 = b.col5
and d.col6 = c.col6;
END LOOP;
END;
Since you say that you are just turning around and exporting the resulting data in SQL Developer, however, the temporary table doesn't seem particularly useful. You could remove all the PL/SQL and just write a single SELECT statement
select a.col2, d.col4
from (select col1, min(col2) as col2, col3
from a_tbl
group by col1, col3) a,
b_tbl b,
c_tbl c,
d_tbl d
where b.col1 = a.col1
and c.col5 = b.col5
and d.col6 = c.col6;

Resources