Subquery in group by (ORACLE 9i) - oracle

I have a query that looks similar to the one below (albeit more complicated). When running it I get the following error: ORA-22818: Subquery expressions not allowed here in my group by statement.
What is the best way for me to get around this issue?
SELECT table1.ID
NVL(fget_office(fget_last_catc_id_by_date((SELECT MAX(table3.date) FROM table3 INNER JOIN table1 ON table1.ID = table3.id),table1.NUM), fget_max_split_line_no('FILL',(SELECT MAX table3.tc_id) FROM table3 INNER JOIN table1 ON table1.ID = table3.ID INNER JOIN table4 ON table3.tc_id = table3.tc_id))), table1.distribution) "OFFICE", --eper.DISTRIBUTION "OFFICE",
table1.name
FROM table1
LEFT JOIN table2
ON table1.ID = table2.ID
WHERE table1.company in ('CP01', 'CP02')
GROUP BY table1.ID,
NVL(fget_office(fget_last_catc_id_by_date((SELECT MAX(table3.date) FROM table3 INNER JOIN table1 ON table1.ID = table3.id),table1.NUM), fget_max_split_line_no('FILL',(SELECT MAX table3.tc_id) FROM table3 INNER JOIN table1 ON table1.ID = table3.ID INNER JOIN table4 ON table3.tc_id = table3.tc_id))), table1.distribution),
table1.name

Your code sample looks like you're using GROUP BY just to pull distinct rows. In that case, try this:
SELECT DISTINCT
table1.ID
NVL(fget_office(fget_last_catc_id_by_date((SELECT MAX(table3.date) FROM table3 INNER JOIN table1 ON table1.ID = table3.id),table1.NUM), fget_max_split_line_no('FILL',(SELECT MAX table3.tc_id) FROM table3 INNER JOIN table1 ON table1.ID = table3.ID INNER JOIN table4 ON table3.tc_id = table3.tc_id))), table1.distribution) "OFFICE", --eper.DISTRIBUTION "OFFICE",
table1.name
FROM table1
LEFT JOIN table2
ON table1.ID = table2.ID
WHERE table1.company in ('CP01', 'CP02')
In case you really are doing aggregation in your "real" query, a quick workaround would be to use a Common Table Expression (CTE), which is supported in Oracle 9i. This example assumes you're summing a column named some_value:
WITH x AS (
SELECT table1.ID
NVL(fget_office(fget_last_catc_id_by_date((SELECT MAX(table3.date) FROM table3 INNER JOIN table1 ON table1.ID = table3.id),table1.NUM), fget_max_split_line_no('FILL',(SELECT MAX table3.tc_id) FROM table3 INNER JOIN table1 ON table1.ID = table3.ID INNER JOIN table4 ON table3.tc_id = table3.tc_id))), table1.distribution) "OFFICE", --eper.DISTRIBUTION "OFFICE",
table1.name,
some_value
FROM table1
LEFT JOIN table2
ON table1.ID = table2.ID
WHERE table1.company in ('CP01', 'CP02')
)
SELECT ID, OFFICE, name, SUM(some_value)
FROM x
GROUP BY ID, Office, name

It looks to me like the results of those functions are directly or indirectly determined by the values of table1.
If so, you can perform the distinct operation on a simple set of data from table1 and table2 and apply the functions afterwards. This would reduce the number of calls to the functions and improve efficiency.
with cte1 as (
select
table1.id
table1.num
table1.distribution,
table1.name
from
table1 left join table2 on (table1.id = table2.id)
where
table1.company in ('CP01', 'CP02'))
select
cte1.id,
coalesce(
fget_office(
fget_last_catc_id_by_date(
(select max(table3.date)
from table3 inner join cte1 on cte1.id = table3.id),
cte1.num),
fget_max_split_line_no(
'FILL',
(select max(table3.tc_id)
from table3 inner join cte1 on cte1.id = table3.id
inner join table4 on table3.tc_id = table3.tc_id))),
table1.distribution) office
cte1.name
from cte1
/
You might as well get used to using Coalesce() instead of Nvl() -- it's ANSI compliant, more flexible, and features short-circuit evaluation so it's handy of your codebase has a lot of PL/SQL functions that get called in SQL.

Related

I am trying to combine 3 tables for to get a distinct combination as below

SELECT TYPE_DETAILS(a.column1,c.column2,c.column3) BULK COLLECT INTO OUT_DETAILS
FROM TABLE1 a
INNER JOIN TABLE2 b ON a.column2 = b.column2
INNER JOIN TABLE3 c ON a.column3 = c.column3;
I only want combinations for distinct values of a.column1 . If I apply distinct as below i am getting error
SELECT TYPE_DETAILS(DISTINCT a.column1,c.column2,c.column3) BULK COLLECT INTO OUT_DETAILS
FROM TABLE1 a
INNER JOIN TABLE2 b ON a.column2 = b.column2
INNER JOIN TABLE3 c ON a.column3 = c.column3;
Why don't you use sub-query:
SELECT TYPE_DETAILS(column1,column2,column3)
BULK COLLECT INTO OUT_DETAILS FROM
(SELECT DISTINCT a.column1,c.column2,c.column3
FROM TABLE1 a
INNER JOIN TABLE2 b ON a.column2 = b.column2
INNER JOIN TABLE3 c ON a.column3 = c.column3);

Oracle: Convert rows into columns for output of joined table queries

SELECT ABC.ID, ABC.URL1, ABC.URL2,
DECODE(ABC.TEXT,'URL3' ,ABC.URL),
DECODE(ABC.TEXT,'URL4',ABC.URL),
DECODE(ABC.TEXT,'URL5',ABC.URL),
DECODE(ABC.TEXT,'URL6',ABC.URL),
DECODE(ABC.TEXT,'URL7',ABC.URL),
DECODE(ABC.TEXT,'URL8',ABC.URL),
DECODE(ABC.TEXT,'URL9',ABC.URL)
FROM (SELECT * FROM (SELECT t1.ID, t2.URL1, t2.URL2,
t4.TEXT AS TEXT, t3.URL AS URL
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id=t2.id2
LEFT JOIN table4 t3 ON t3.id=t2.id2
LEFT JOIN table4 t4 ON t3.id3=t4.id
WHERE t1.id='VALUE'))ABC;
I want the output as below:
and values for those urls in respective columnst1
Below code worked for me:
SELECT DEF.ID, DEF.URL1, DEF.URL2,
MAX(DECODE(ABC.TEXT,'URL3' ,ABC.URL)) URL3,
MAX(DECODE(ABC.TEXT,'URL4',ABC.URL)) URL4,
MAX(DECODE(ABC.TEXT,'URL5',ABC.URL)) URL5,
MAX(DECODE(ABC.TEXT,'URL6',ABC.URL)) URL6,
MAX(DECODE(ABC.TEXT,'URL7',ABC.URL)) URL7,
MAX(DECODE(ABC.TEXT,'URL8',ABC.URL)) URL8,
MAX(DECODE(ABC.TEXT,'URL9',ABC.URL)) URL9
FROM (SELECT * FROM (SELECT t1.ID, t2.URL1, t2.URL2,
t4.TEXT AS TEXT, t3.URL AS URL
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id=t2.id2
LEFT JOIN table4 t3 ON t3.id=t2.id2
LEFT JOIN table4 t4 ON t3.id3=t4.id
WHERE t1.id='VALUE')ABC) DEF
GROUP BY DEF.ID, DEF.URL1, DEF.URL2;

Union and With Clause SubQuery Oracle

I need immediate help in solving my problem before using in production:
Am using below SQL in Oracle11g
With sub_query1 as (select t1.column1, t2.column2, t1.id from table1 t1
inner join table2 t2 on t1.id = t2.id )
SELECT t3.column3 s1.* FROM sub_query1 s1
INNER JOIN table3 t3 ON t3.id=s1.id
union
SELECT t4.column4 s1.* FROM sub_query1 s1
INNER JOIN table4 t4 ON t4.id=s1.id;
This was working when I was using as is, but when add one subquery before SUB_QUERY1 it is not working, it is just returning 0 rows without any error:
With
main_sub_query as (select ta.id from tableA ta)
--second subquery
, sub_query1 as (select t1.column1, t2.column2, t1.id from table1 t1
inner join table2 t2 on t1.id = t2.id
inner join main_sub_query mq ON mq.id=t1.id
)
SELECT t3.column3 s1.* FROM sub_query1 s1
INNER JOIN table3 t3 ON t3.id=s1.id
union
SELECT t4.column4 s1.* FROM sub_query1 s1
INNER JOIN table4 t4 ON t4.id=s1.id;
When I remove the union and later part it is returning data, not sure what is the issue.

Fetching other rows of table when performing inner join over multiple fields (oracle query)

select pmt.col1,table2.col1,table2.col3,table3.col1,table3.col1
from table2 inner join (select distinct
col1,col2 from table1) pmt on
table2.col1=pmt.col1 inner join table3 on
table3.col1=table1.col2 where table2.col2 is null;
Is there any way I can select pmt.col3(which is other column of table1) in this very query only.
Thanks very much
Simply select the column in a the sub query. Use for instance max for limiting the result set to one record:
select pmt.col1,
(select max(col3)
from table1 t1
where t1.col1 = pmt.col1
and t1.col2 = pmt.col2) col3,
table2.col1,
table2.col3,
table3.col1,
table3.col1
from table2
inner join (select distinct col1,col2
from table1) pmt
on table2.col1=pmt.col1
inner join table3
on table3.col1=table1.col2
where table2.col2 is null;

Oracle JOIN USING + Subquery : ora-00904 string: invalid identifier

i m having a little syntax problem in my query (simplified) :
select *
from table1 t1
inner join table2 t2 using (pk1)
inner join table3 t3 using (pk2)
where not exists (select1 from table4 t4 where t4.pk1 = t1.pk1)
By using the "using" keyword, oracle doesnt allow table identifier in front of the column name (eg : t1.pk1, only pk1 can be used)
If i write :
select *
from table1 t1
inner join table2 t2 using (pk1)
inner join table3 t3 using (pk2)
where not exists (select1 from table4 t4 where t4.pk1 = pk1)
This query will not give the expected results.
But since i am using an "exists" subquery, how can i join this subquery ?
Of course, i suppose i could write this query another way and avoid the exists, or i could NOT use "using".
But is it possible to have "join / using" combined with a subquery in the where clause ?
Edit : using Oracle 10gR2
Interesting problem! The best I can manage while still using USING is:
select * from
( select *
from table1 t1
inner join table2 t2 using (pk1)
inner join table3 t3 using (pk2)
) v
where not exists (select1 from table4 t4 where t4.pk1 = v.pk1)
You cannot use the table qualifiers with natural joins.
This query:
select 1 from table4 t4 where t4.pk1 = pk1
is being parsed as
select 1 from table4 t4 where t4.pk1 = t4.pk1
and NOT EXISTS over it always returns false if there is but a single record in table4.
Just use explicit JOIN conditions:
WITH table1 AS
(
SELECT 1 AS pk1
FROM dual
),
table2 AS
(
SELECT 1 AS pk1, 1 AS pk2
FROM dual
),
table3 AS
(
SELECT 1 AS pk2
FROM dual
),
table4 AS
(
SELECT 2 AS pk1
FROM dual
)
SELECT *
FROM table1 t1
JOIN table2 t2
ON t2.pk1 = t1.pk1
JOIN table3 t3
ON t3.pk2 = t2.pk2
WHERE NOT EXISTS
(
SELECT 1
FROM table4 t4
WHERE t4.pk1 = t1.pk1
)

Resources