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

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;

Related

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.

Merge table data

Table1 Table2 Table3 Table4
Sl Name City index len bre col tax income price dicount org
1 ABC XYZ 1 10 12 1 23 40 1 10 XYZ
2 DEF asd 2 12 14 2 24 42 2 6 asd
3 ghi jkl 3 78 89 3 0 gah
These entries correspond to respective tables. I want to fetch data from all 4 tables irrespective of whether values are present in Table2 or not. Any null value in Table2 should not hamper the output.
select tab1.Name,
tab2.len,
tab3.tax,
tab4.org
From Table1 tab1,
Table2 tab2,
Table3 tab3,
Table4 tab4
where tab1.sl=tab2.index(+)
AND tab2.index(+)=tab3.col
AND tab3.col=tab4.price;
This query only returns results for those Sl for which there is entry in table 2. How can I resolve this?
To use a proper ANSI left join:
select tab1.Name,
tab2.len,
tab3.tax,
tab4.org
From Table1 tab1
inner join Table3 tab3 on tab1.sl.tab3.col
inner join Table4 tab4 on tab3.col=tab4.price
left join Table2 tab2 on tab1.sl=tab2.index;
This makes your code much more readable.
Try following ---
select tab1.Name,
tab2.len,
tab3.tax,
tab4.org
From
Table1 tab1 left join Table2 tab2
on tab1.sl=tab2.index(+) join Table3 tab3
on tab2.index(+)=tab3.col join Table4 tab4
on tab3.col=tab4.price;
Look, you should move from the 1990s into the early 2000s, by rewriting your query without the 'orrible omega-join (+) syntax.
Converting omega to join, your query comes out like this.
SELECT tab1.Name,
tab2.len,
tab3.tax,
tab4.org
FROM Table1 tab1,
left join Table2 tab2 ON tab1.sl=tab2.index
right join Table3 tab3 ON tab2.index=tab3.col
inner join Table4 tab4 ON tab3.col=tab4.price;
And, then the apparently chaotic combination of right, left, and inner join operations hints at the solution to your problem.
Change over to all left joins and your Table1 rows won't be suppressed when they don't match other tables.
SELECT tab1.Name,
tab2.len,
tab3.tax,
tab4.org
FROM Table1 tab1
LEFT JOIN Table2 tab2 ON tab1.sl=tab2.index
LEFT JOIN Table3 tab3 ON tab2.index=tab3.col
LEFT JOIN Table4 tab4 ON tab3.col=tab4.price;
Even if you must use the old omega join syntax, you should use it in a way which won't suppress rows from Table1
select tab1.Name,
tab2.len,
tab3.tax,
tab4.org
From Table1 tab1,
Table2 tab2,
Table3 tab3,
Table4 tab4
where tab1.sl=tab2.index(+)
AND tab2.index=tab3.col(+)
AND tab3.col=tab4.price(+);
The position of the (+) on the right means it's a left join, and vice versa.

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;

Subquery in group by (ORACLE 9i)

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.

How to use join on three tables

I have three tables
Table1 Table2 and Table3.
Table1 having column ID.
Table2 having column names ID,Name.
Table three having column name Name.
Now i want to retrive ID from table1 which is there in Table2 by so that the name associated with ID in table to should be in Table3.
Table1.ID=Table2.ID(Table2.Name=Table3.Namw).
Without using IN operator.Only joins.
select table1.id, table2.name
from table1
join table2 on table2.id = table1.id
join table3 on table3.name = table2.name
select distinct t1.ID
from Table1 t1
,Table2 t2
,Table3 t3
where t1.ID = t2.ID
and t2.Name = t3.Name
;
or
select t1.ID
from Table1 t1
where exists (
select 1
from Table2 t2
,Table3 t3
where t1.ID = t2.ID
and t2.Name = t3.Name
);

Resources