Accessing aliased tables - oracle

This question is wrong. I had some very big misunderstanding about how union works. I am reading about it now.
edit 04.12.2016
If you are still intersted, you can go here
Selecting the right column
I have something like this
with table3 as
(
select t1.c1, t1.c2...
from table1 t1
union all
select t2.c1, t2.c2...
from table2 t2
)select * from table3
I need to insert all rows from above in another table
insert into table4 t4
(
t4.c1, t4.c2...
)
select t3.c1, t3.c2...
from table3 t3
My question is, will this insert work. I have clumns in table 1 and 2 named the same, will I need to reference them somehow differently?
Do I need to write it like this?
insert into table4 t4
(
t4.c1, t4.c2...
)
select t3.t1.c1, t3.t1.c2, t3.t2.c1...
from table3 t3

with is part of select statement. You can insert result of select and you can use with in this select. Maybe syntax is not the most intuitive but this should work:
insert into table4
with table3 as
(
select t1.c1, t1.c2...
from table1 t1
union all
select t2.c1, t2.c2...
from table2 t2
) select * from table3;
And no you don't need (even can't) use double aliases.

No alias needed
if the column match you could simply use insert select
insert into table4
( select t1.c1, t1.c2...
from table1 t1
union all
select t2.c1, t2.c2...
from table2 t2)
otherwise you should declare the column name
insert insert into table4(c1, c2... )
( select t1.c1, t1.c2...
from table1 t1
union all
select t2.c1, t2.c2...
from table2 t2)

Assuming that you needto use that UNION ALL, instead of single insert-as-select statements to insert into another table, you can try to use different aliases for columns from different tables:
with table1 as
(
select t2.name as t2_name,
t2.address as t2_address,
t2.age as t2_age,
null as t3_name,
null as t3_address,
null as t3_age,
from table2 t2
union all
select null,
null,
null,
t3.name,
t3.address,
t3.age
from table3 t3
)

Related

How do I insert values in a table using inner join?

I am trying to insert data into table1.col1 using following query.
INSERT INTO table1 t1( t1.col1)
SELECT t2.col1
FROM table2 t2
WHERE t1.col2= t2.col2;
Apparently, it wouldn't work(flawed logic maybe). How can I achieve similar results.
Let me know if I don't make sense.
INSERT INTO table1 (col1)
SELECT t2.col1
FROM table2 t2
INNER JOIN table1 t1 on t1.col2= t2.col2;
INSERT INTO table1 (col1)
SELECT t2.col1
FROM table1 t1,table2 t2
WHERE t1.col2= t2.col2;
It seems you need a MERGE statement with MATCHED(for already existing rows in table1) and
NOT MATCHED(for rows not inserted into table1 yet) options :
MERGE INTO table1 t1
USING table2 t2
ON (t1.col2 = t2.col2)
WHEN MATCHED THEN
UPDATE SET t1.col1 = t2.col1
WHEN NOT MATCHED THEN
INSERT (col1,col2)
VALUES (t2.col1, t2.col2);
Demo
So, I was not looking to insert but to update...stupid question I know :)
This is what I was looking for.
update table1 t1 set t1.col1 = (select t2.col1 from table2 t2 where t1.col2 = t2.col2);

Declare statement in PL/SQL for a part of the query

I have a query like the following:
select t1.varid, t1.var1, t1.var2, t1.vardata, t2.varid, t2.var1, t2,.var2
from table1 t1, table2 t2
where t1.varid = t2.varid
and t1.vardata between to_date('20170807','YYYYMMDD') and to_date('20170808','YYYYMMDD')
Now the question is:
I need to extract the data not only in the data range specified in the query above, but I want to extract many other ranges in the same query.
To do that, I used UNION ALL and it works. The problem is that I have to re-write this part many times:
select t1.varid, t1.var1, t1.var2, t1.vardata, t2.varid, t2.var1, t2, var2
from table1 t1, table2 t2
where t1.varid = t2.varid
Is there a tip for how to define select t1.varid... as a named variable in order to avoid a long boring repeated query?
Any other solutions are welcome.
As discussed in the chat you can do it as below:
SELECT t1.varid as col1,
t1.var1 as col2,
t1.var2,
t1.vardata,
t2.varid,
t2.var1,
t2,
.var2
FROM table1 t1, table2 t2
WHERE t1.varid = t2.varid
AND t1.vardata BETWEEN TO_DATE ('20170807', 'YYYYMMDD')
AND TO_DATE ('20170808', 'YYYYMMDD')
--- Give date ranges.
OR t1.vardata BETWEEN TO_DATE ('20170907', 'YYYYMMDD')
AND TO_DATE ('20171008', 'YYYYMMDD')
OR ....
OR ....
You can try fetching the dates directly from a table like this instead of rewriting repeated statements :
Select 'select t1.varid, t1.var1, t1.var2, t1.vardata, t2.varid, t2.var1, t2,.var2
From table1 t1, table2 t2 where t1.varid = t2.varid and t1.vardata between to_date('''+MY_DATE+''', ''yyyymmdd'')' from tableofdate
Below is the schema i used.This is just a sample.Please edit it as per your requirements
create table tableofdate(my_date varchar(100))
insert into tableofdate values ('20170808')

ORACLE SQL: unable to left join 3 tables

How do I join 3 tables with left outer join? I was able to do left outer join between table1 and table2, but not table3.
I tried the following, but don't know how to join with table3.
select tab1.id, tab2.status, tab3.job_history
from table1 tab1
left outer join table2 tab2 on tab1.id=tab2.id
where tab1.job_title='accounting'
My table schemas are:
table 1:
id number(5) primary key,
status_code number(5),
job_title varchar2(20)
name varchar2(30)
table 2:
status_code number(5) primary key,
status varchar2(15)
table 3:
id number(5)
job_history varchar2(20)
Conditions:
table1.status_code can be null
table1.id may be not have any match for table3.id
I want to find the record in table1 that has table1.job_title = 'accounting' or in table3 has table3.job_history = 'accounting' when table1.id = table3.id and also get the table2 status with table1.status_code = table2.status_code
I suspect you're wanting to join table2 to table1 on status_code instead of id, as there is no ID column in table2. To join the third table, just add another LEFT OUTER JOIN (or any other JOIN).
select
tab1.id,
tab2.status,
tab3.job_history
from
table1 tab1
left outer join
table2 tab2 on tab2.status_code = tab1.status_code
left outer join
table3 tab3 on tab3.id = tab1.id
where
tab1.job_title='accounting' or tab3.job_history = 'accounting'
Since you have not same fields on all tables, to match your conditions, you probably will find easier way to run join like:
select
tab1.id,
tab2.status,
tab3.job_history
from
table1 tab1,
table2 tab2,
table3 tab3
where
tab1.job_title='accounting'
--ADD ADITIONAL FILTERING HERE
Query with join on 3 tables is look like this:
select
tab1.id,
tab2.status,
tab3.job_history
from
table1 tab1
left outer join
table2 tab2 on tab1.id=tab2.id
left outer join
table3 tab3 on tab3.id = tab1.id
where
tab1.job_title='accounting'
This SQL assumes that there is a one-to-one relationship between table 1, table 2 and table 3
select tab1.id, tab2.status, tab3.job_history
from table1 tab1
left outer join table2 tab2 on tab2.status_code = tab1.status_code
left outer join table3 tab3 on tab3.id = tab1.id
where tab1.job_title = 'accounting' or tab3.job_history = 'accounting'
Table 3 looks like it contains some form of job history, so it is likely there is going to more than one record in Table 3 for each record on Table 1. If this is the case you will need to perform a sub-query to find all people that currently or previously have a job title of accounting, i.e.
select tab1.id, tab2.status, tab1.job_title
from table1 tab1
left outer join table2 tab2 on tab2.status_code = tab1.status_code
where tab1.job_title = 'accounting' or
tab1.id in (select id from tab3 where job_history = 'accounting')

2 Datatables to 1

Let's say i have Datatable1 that has "Colum1" , "colum2"
and another table, Datatable2 with "Colum3" , "colum4"
I need to create Datatable3 that will contain all the columns "Colum1" , "colum2", "Colum3" , "colum4"
I need something smart, like the DefaultView.ToTable() method that does it for one table.
Thanks
As you didn't mention any language or DB server type, here's something that might work (not tested really) on SQL Server 2005:
CREATE TABLE #temp (col1 <type>, col2 <type>, col3 <type>, col4 <type>)
INSERT INTO #temp
(
SELECT t1.Column1, t1.Column2, t2.Column3, t2.Column4
FROM Datatable1 t1 INNER JOIN Datatable2 t2 ON t2.<PrimaryKeyField> = t1.<PrimaryKeyField>
UNION
SELECT t1.Column1, t1.Column2, t2.Column3, t2.Column4
FROM Datatable2 t2 INNER JOIN Datatable1 t1 ON t1.<PrimaryKeyField> = t2.<PrimaryKeyField>
)
SELECT * FROM #temp

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