Multi row to single row conversion in oracle - sql

I have below tables.
Table1
Col1,col2,col3,col4
1,2,3,''
3,4,5,''
Table2
col5,col6
4,5
1,1
Table3
col7
7
0
Want the output as below:
output table:
col1,col2,col3,col4,col5,col6,col7
4,6,8,'',5,6,7
Could you please help with the above requirement.

Aggregate before joining:
select *
from (select sum(col1) as col1, sum(col2) as col2, sum(col3) as col3
from t1
) t1 cross join
(select sum(col5) as col5, sum(col6) as col6
from t2
) t2 cross join
(select sum(col7) as col7
from t3
) t3;
Note: Oracle treats '' as NULL, so SUM() works fine on that column.

Related

Join or Union table with same Characteristics and different Measures

I would like to understand the easy/better way to join 2 tables with same characteristics and different measures as an example described below:
tab1
Col1
Col2
Measure1
1
1
10
1
2
5
tab2
Col1
Col2
Measure2
1
1
20
2
1
25
Expected Result
Col1
Col2
Measure1
Measure2
1
1
10
20
1
2
5
0
2
1
0
25
Questions:
How to avoid message: Ambiguous column name col1?
How to create a correct Join?
I have tried:
select col1, col2, t1.Measure1, t2.Measure2
from tab1 t1
full outer jon tab2 t2
on t1.col1 = t2.col1
and t1.col2 = t2.col2
I have tried a Union and it works, but i am looking a easy way using joins:
Select col1, col2, Measure1, 0 as Measure2 From tab1
Union
Select col1, col2, 0 as Measure1, Measure2 From tab2
The full join is the correct approach. But you need to disambiguate col1 and col2 in the select clause: both tables have both columns, so it is unclear to which column an unprefixed col1 refers.
A typical approach uses coalesce():
select
coalesce(t1.col1, t2.col1) col1,
coalesce(t1.col2, t2.col2) col2,
coalesce(t1.measure1, 0) measure1,
coalesce(t2.measure2, 0) measure2
from tab1 t1
full outer jon tab2 t2
on t1.col1 = t2.col1 and t1.col2 = t2.col2
Note that you also need coalesce() around the measures to return 0 instead of null on "missing" values.
In some databases (eg Postgres), you can use the using syntax to declare the join conditions for columns that have the same name across the tables ; this syntax automagically disambiguates the unprefixed column names, so:
select
col1,
col2,
coalesce(t1.measure1, 0) measure1,
coalesce(t2.measure2, 0) measure2
from tab1 t1
full join tab2 t2 using (col1, col2)
You should reference source tables for col1 and col2 as well.
As you're using FULL OUTER JOIN I'd recommend using COALESCE statement.
SELECT COALESCE(t1.col1, t2.col1) as col1,
COALESCE(t1.col2, t2.col2) as col2,
t1.Measure1,
t2.Measure2
FROM tab1 t1
FULL OUTER JOIN tab2 t2
on t1.col1 = t2.col1
and t1.col2 = t2.col2

Insert into one table from another Postgres based on two columns

I have two tables with the same columns, There are no unique columns for these tables. Lets say the columns are Col1, Col2, Col3 and Col4. The tables are T1 and T2.
What I want to do is insert all the rows from T2 to T1 where Col1 & Col2 combinations do not exist in T1 already. Col1 is a string and Col2 is an int.
So for example Col1 = "APPLE" and Col2 = "2019". If a row contains Col1 = "APPLE" and Col2=2019 in T2 I do not want to insert it into T1 whereas if a row contains Col1 = "APPLE" and Col2=2020 then I want to insert it into T1.
I am trying to find the easiest solution to do this and cant seem to find a straightforward way using INSERT INTO WHERE NOT EXISTS or using UPSERT.
You can use insert ... select ... where not exists with tuple equality to compare (col1, col2):
insert into t1(col1, col2, col3, col4)
select * from t2
where not exists (
select 1 from t1 where (t1.col1, t1.col2) = (t2.col1, t2.col2)
)
With NOT EXISTS:
insert into t1(Col1, Col2, Col3, Col4)
select Col1, Col2, Col3, Col4
from t2
where not exists (
select 1 from t1
where t1.Col1 = t2.Col1 and t1.Col2 = t2.Col2
)
See a simplified demo.

How to improve this inline query?

I'm a sales-force developer, I got a requirement to write a SQL query and I did it, but the performance in very low. Could you please help me here?
My query is like this:
select col1, col2,col3,col4
from table1
where col1 is not null
and col2='ABC'
and (col3 IN (SELECT field1 FROM table 2)
OR col4 in('A','B','C'))
Is there someway I can optimize this for better performance?
Update
I used left outer join to achieve it, Is that the correct way?
Try these queries:
SELECT col1, col2,col3,col4 FROM TABLE1 T1
WHERE (EXISTS (SELECT 1 FROM TABLE2 T2 WHERE T1.COL3 = T2.FIELD1)
OR COL4 IN ('A','B','C'))
SELECT col1, col2,col3,col4 FROM TABLE1 T1
WHERE EXISTS (SELECT 1 FROM TABLE2 T2 WHERE T1.COL3 = T2.FIELD1)
UNION
SELECT col1, col2,col3,col4 FROM TABLE1 T1 WHERE COL4 IN ('A','B','C')

How to get the following join query

How to get the following join
input:
table1: table2:
col1 Col1 col2 col3
A A 1 2
B B 4 5
C
output:
col1 col2 col3
A 1 2
B 4 5
c - -
SELECT t1.col1, t2.col2, t2.col3
FROM table1 t1
LEFT JOIN table2 t2 ON t1.col1=t2.col1
;
You can do this using full outer join:
select coalesce(t1.col1, t2.col1), t2.col2, t2.col3
from table1 t1 full outer join
table2 t2
on t1.col1 = t2.col1;
This returns all rows from both tables, even those that don't match (it is a left and right outer join at the same time).
You can also do this using union all and aggregation:
select col1, max(col2) as col2, max(col3) as col3
from ((select col1, NULL as col2, NULL as col3
from table1
) union all
(select col1, col2, col3
from table2
)
) t
group by col1;
select t1.col1, t2.col2, t2.col3
from table1 t1
left outer join table2 t2
on t1.col1 = t2.col1
Maybe something like this if you wan't the '-'
SELECT t1.col1, coalesce(t2.col2,'-') as col2, coalesce(t2.col3,'-') as col3
FROM table1 t1
LEFT JOIN table2 t2 ON t1.col1=t2.col1
See my sqlfiddle
create table table1(
col1 char(1)
);
insert into table1 values('A');
insert into table1 values('B');
insert into table1 values('C');
create table table2(
col1 char(1),
col2 int,
col3 int
);
insert into table2 values('A',1,2);
insert into table2 values('B',4,5);
select
t1.col1,
coalesce(t2.col2,'-'),
coalesce(t2.col3,'-')
from
table1 t1
left join table2 t2 on t1.col1=t2.col1
;
http://sqlfiddle.com/#!2/bc768/2
You need to do an outer join
SELECT *
FROM table1 t1,
table2 t2
WHERE t1.col1 = t2.col1(+)

Using the names of columns stored within fields to retrieve data from a different table

I was wondering if there exists code to accomplish the following in SQL-Server 2008?
Table 1:
id column name
-------------------
1 col1
2 col2
3 col3
4 col2
Table 2:
col1 col2 col3
--------------------
a b c
Result Table:
id data
--------------------
1 a
2 b
3 c
4 b
Thanks in advance, I really have no idea how to do this.
You can use UNPIVOT table2 to access the data from the columns:
select t1.id, t2.value
from table1 t1
left join
(
select value, col
from table2
unpivot
(
value
for col in (col1, col2, col3)
) u
) t2
on t1.name = t2.col
see SQL Fiddle with Demo
Or you can use a UNION ALL to access the data in table2:
select t1.id, t2.value
from table1 t1
left join
(
select col1 value, 'col1' col
from table2
union all
select col2 value, 'col2' col
from table2
union all
select col3 value, 'col3' col
from table2
) t2
on t1.name = t2.col
see SQL Fiddle with Demo
I dont see how you do it withou a column connection them:
Table1:
ID
ColumnName
Table2:
Table1ID
Letter
Select table1.id, table2.Letter
from table1
inner join table2 on table1.ID = table2.Table1ID
You can do this with a case statement and cross join:
select t1.id,
(case when t1.columnname = 'col1' then t2.col1
when t1.columnname = 'col2' then t2.col2
when t1.columnname = 'col3' then t2.col3
end) as data
from table1 t1 cross join
table2 t2