Table alias is not recognized in subquery Oracle - sql

I have SELECT statement with LEFT JOIN and joined tables are sub-queries. And Oracle could not recognize alias of the first sub-query in the second one. It works for DB2 but does not work for Oracle.
How I can implement it or rewrite my query?
SELECT *
FROM
(SELECT E.C3 AS COLUMN3
, E.C4 AS COLUMN4
FROM TBL_1 D
, TBL_2 E
WHERE D.C6 = E.C6 ) B
LEFT JOIN TABLE
(SELECT C.C1
FROM TBL_3 C
WHERE
C.C7 = 'hello'
AND B.C3 = C.C8
UNION ALL
SELECT C.C1
FROM TBL_3 C
WHERE
C.C7 = 'world'
AND B.C4 = C.C8
) A
ON 1 = 1
Oracle error message:
ORA-00904: "B"."C3": invalid identifier

You can simplify this query to the following, removing the sub-queries:
Select A.Col1, B.Col2
From tbl_AJoin A
Left Join tbl_BJoin B On A.col1 = B.col1

You have a syntax error. This:
select * from (select col1 from tbl_Ajoin) A
left join table (select col2 from tbl_Bjoin where A.col1 = tbl_Bjoin.col1) B
ON 1 = 1
should be this:
select * from (select col1 from tbl_Ajoin) A
left join (select col2 from tbl_Bjoin where A.col1 = tbl_Bjoin.col1) B
ON 1 = 1
or more specifically, this:
left join table (select
should not have the word table. It should be this:
left join (select

Related

Oracle SQL: How to replace distinct with where exists

I've read that using a where exists clause could usually be more efficient than writing select distinct. How could I rewrite the below 2 queries using the where exists condition? Not sure if query2 is eligible for this clause or this only applies to joins.
Query 1:
SELECT DISTINCT
e.field1,
regexp_substr(substr(TRIM(d.field2), 1, 2), '[A-Za-z]+', 1, 1) postal_group
FROM
table1 e
JOIN table1 f ON f.field0 = e.field0
JOIN table2 g ON g.field3 = f.field3
JOIN table3 g ON g.field4 = f.field4
JOIN table4 a ON a.field5 = g.field5
JOIN table5 b ON ( b.field6 = a.field6
AND b.field7 = a.field7 )
JOIN table6 c ON ( c.field8 = b.field8
AND c.field9 = b.field9 )
JOIN table7 d ON ( d.field10 = c.field10
AND d.field11 = c.field11 )
Query 2:
SELECT DISTINCT
field
FROM
table1
WHERE
condition = 'value'
For your second query you can use group by clause to avoid DISTINCT.
SELECT field
FROM
table1
WHERE
condition = 'value'
Group by field
Please try below query with where exists instead of Distinct:
SELECT
e.field1,
regexp_substr(substr(TRIM(d.field2), 1, 2), '[A-Za-z]+', 1, 1) postal_group
FROM
table1 e
where exists
(
select 1 from table1 f
JOIN table2 g ON g.field3 = f.field3
JOIN table3 g ON g.field4 = f.field4
JOIN table4 a ON a.field5 = g.field5
JOIN table5 b ON ( b.field6 = a.field6
AND b.field7 = a.field7 )
JOIN table6 c ON ( c.field8 = b.field8
AND c.field9 = b.field9 )
JOIN table7 d ON ( d.field10 = c.field10
AND d.field11 = c.field11 )
where f.field0 = e.field0
)
You can't avoid a join with d because you need a column from it. Therefore the best you can do is:
select e.column1
, d.column2 as postal_group
from table1 e
join table7 d
on d.column10 = c.column10
and d.column11 = c.column11
where exists
( select 1 from table1 f
join table2 g on g.column3 = f.column3
join table3 h on h.column4 = f.column4
join table4 a on a.column5 = h.column5
join table5 b on b.column6 = a.column6 and b.column7 = a.column7
join table6 c on c.column8 = b.column8 and c.column9 = b.column9
where f.column0 = e.column0 );
You only need distinct if table7.column2 can have duplicate values for a (column10, column11) combination.
This may or may not be more efficient than the original version - compare timings, execution plans, reads etc.
(I've renamed 'fields' as columns because that's what tables have. Also there are no brackets in a join clause and adding them tends to confuse code formatters.)

Oracle SQL: Multiple With statement

I am creating a giant SQL query:
Select * from (With tab1 AS ( Select * from abc)
,tab2 AS (select * from cde)
,tab3 AS (select * from tab2)
.
.
.
,tabz AS (select a, b from xyz
UNION
select a, b from cde)
Select tab1.*, tab3.* from
tab1
LEFT OUTER JOIN tab2 ON tab1.a = tab2.b
...
LEFT OUTER JOIN tabz on tab1.a = tabz.a) A
Now using the above as 1 table I need to create another long SQL to calculate percentages and other things with other tables tables.
Say above table is A
then
Select bbb.a,bbb.b from bbb
JOIN A ON bbb.a = A.a and then name it as B
And then finally join A LEFT OUTER JOIN B.
It is a massive Query and I know we can not have Nested WITH statement. Does anyone have any easy way to complete this? OR any suggestion?
I only need to accomplish this using oracle SQL queries.
I think you can rephrase your query as:
WITH
tab1 AS (select * from abc)
,tab2 AS (select * from cde)
,tab3 AS (select * from tab2)
.
.
.
,tabz AS (select a, b from xyz
UNION
select a, b from cde)
,a as (
Select tab1.*, tab3.*
from tab1
LEFT OUTER JOIN tab2 ON tab1.a = tab2.b
...
LEFT OUTER JOIN tabz on tab1.a = tabz.a
),
b as (
Select bbb.a,bbb.b from bbb JOIN A ON bbb.a = A.a
)
select *
from a
left join b on ...

How to LEFT JOIN in DB2 iseries with first row?

I have need a query that JOIN a TABLE with A first row of other table value based:
SELECT * FROM TABLEA A LEFT JOIN
(SELECT * from TABLEB
WHERE FIELD1 <> '3' and FIELD2 = 'D' AND A.CODE=CODE
FETCH FIRST 1 ROW ONLY
) B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
but DB2 return ERROR because can't use A.CODE
How can solve this?
You need to use the nested table expression:
SELECT * FROM TABLEA A LEFT JOIN
LATERAL (SELECT * from TABLEB
WHERE FIELD1 <> '3' and FIELD2 = 'D' AND A.CODE=CODE
FETCH FIRST 1 ROW ONLY
) B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
This is a highly optimized statement.
Your not getting any data from tableb and your going for first row so you just need exists clause.
select a.* from tablea a
where exists (select * from tableb b
where a.fielda = b.fielda
and a.fieldb = b.fieldb
and b.code = a.code
and b.field2 = 'd' and b.field1 <> '3')
You can use the OLAP function row_number() to rank the records according to somefield(s) within a (fielda,fieldb,code) group. Somefield might be a transaction id, or sequence, for example. The order by clause is optional there, but without it, you might be randomly picking which record is the first in the group.
WITH B AS
(SELECT *,
row_number() over (partition by fielda,fieldb,code
order by somefield
) as pick
from TABLEB
WHERE FIELD1 <> '3'
and FIELD2 = 'D'
)
SELECT *
FROM TABLEA A LEFT JOIN B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
and A.CODE = B.CODE
where pick=1

update table with join without PK in oracle

UPDATE
(
SELECT
a.COL1
FROM
TABLE1 a,
TABLE2 b,
TABLE3 c
WHERE
a.name = b.name
c.ccol = b.ccol AND
AND b.col1 = 'anyvalue'
AND a.col2 = 'anothervalue'
) u
SET
u.COL1 = 'VALUE'
This query does not work, since TABLE1 does not contains PK. How to write such a query ?
The following should achieve what it looks like you are trying to achieve above:
UPDATE TABLE1
SET COL1 = 'VALUE'
WHERE EXISTS
( SELECT 1
FROM TABLE2 B
INNER JOIN TABLE3 C
ON B.Ccol = C.Ccol
WHERE b.Name = Table1.Name
AND b.Col1 = 'AnyValue'
AND c.Col1 = 'AnotherValue'
)
I've never worked in oracle, but try something like this. Not having a pk shouldn't be an issue, as long as your joins & where statements are correct.
This is the SQL equivalent of what you're asking for
UPDATE u
SET u.COL1 = 'VALUE'
FROM Table1 AS u
INNER JOIN Table2 AS b ON u.name = b.name
INNER JOIN Table3 AS c ON c.ccol = b.ccol
WHERE b.col1 = 'anyvalue' AND u.col2 = 'anothervalue'

what is wrong with this oracle query?

SELECT *
FROM (SELECT ROWNUM rnum,
query.*
FROM (WITH myQuery AS(
SELECT column_b
FROM table_a a
WHERE a.column_a = 1234)
SELECT b.column_e AS some_column
FROM table_b b,
table_c c,
table_a a
LEFT JOIN table_d d ON c.column_c = d.column_d
JOIN myQuery mq ON a.column_b = mq.column_b
WHERE b.column_b = a.column_b) query)
WHERE rnum > 0
Don't mix ANSI-88 and ANSI-92 JOIN syntax, pick one or the other. Here's your query using ANSI-92 syntax:
WITH myQuery AS (
SELECT column_b
FROM table_a a
WHERE a.column_a = 1234)
SELECT x.*
FROM (SELECT b.column_e AS some_column,
ROWNUM 'rnum'
FROM table_b b
JOIN TABLE_A a ON a.column_b = b.column_b
JOIN myQuery mq ON mq.column_b = a.column_b
JOIN table_c c ON c.? = ?? --need join criteria here
LEFT JOIN table_d d ON c.column_c = d.column_d) x
WHERE x.rnum > 0
Your example lacks what TABLE_C joins on to - hence the ? and ??
I didn't know that WITH clauses can be defined in subqueries - I was sure I'd encountered an error in the past when attempting it in 10g.