SQL Compare Two tables with column value difference - sql

I've 2 tables with exact same structure and I would like compare the column values and display in specific format. I'm new to SQL. I tried with Minus function but its not helping. Find below scenario
Table 1
Key Col1 Col2
1 110 AAA
2 120 BBB
Table 2
Key Col1 Col2
1 111 CCC
2 120 DDD
I need output in below format
Key Field Table1 Table2
1 Col1 110 111
1 Col2 AAA CCC
2 Col2 BBB DDD
How can this be accomplished?
Thanks,
Milind

This is an arcane structure for bringing the tables together. I think this will work:
select t1.col1,
(case when t2.key is not null then 'col2' else 'col1' end) as field,
(case when t2.key is not null then t1.col2
when seqnum = 1 then t1.col1
when seqnum = 2 then t1.col2
end) as Table1,
(case when t2.key is not null then t2.col2
when seqnum = 1 then t2.col1
when seqnum = 2 then t2.col2
end) as Table2
from table1 t1 left join
table2 t2
on t1.key = t2.key and t1.col1 = t2.col1 left join
(select tt2.*, row_number() over (partition by tt2.key order by tt2.key) as seqnum
from table2 tt2
) tt2
on t1.key = tt2.key and t2.key is null;

Related

SQL join two tables that have the same columns, with an overlapping `id` column, but merge based on if table1.col1 >= table2.col1

I want to join two tables that have the same columns, with an overlapping id column, but merge based on if table1.col1 >= table2.col1. This is in SQL.
If table1.col1>=table2.col1, use the columns from table1.
If table1.col1< table2.col1, then use columns from table2.
If the id does not exist in table1 but exists in table2, use the columns from table2
If the id does not exist in table2 but exists in table1, use the columns from table1
For example:
Table1:
id
col1
col2
col3
A
3
5
4
B
1
2
3
C
8
9
7
Table2:
id
col1
col2
col3
A
2
5
6
B
5
7
8
D
2
3
4
I want the result to be:
id
col1
col2
col3
A
3
5
4
B
5
7
8
C
8
9
7
D
2
3
4
I have tried union, full outer join, and CASE statements, but am stuck
I think individual case expressions for each column might be best:
select id,
(case when t1.col1 < t2.col1 then t2.col1 else t1.col1 end) as col1,
(case when t1.col1 < t2.col1 then t2.col2 else t1.col2 end) as col2,
(case when t1.col1 < t2.col1 then t2.col3 else t1.col3 end) as col3
from t1 full join
t2
using (id);
If that is cumbersome, another approach uses not exists:
select t1.*
from t1
where not exists (select 1
from t2
where t2.id = t1.id and t2.col1 > t1.col1
)
union all
select t2.*
from t2
where not exists (select 1
from t1
where t2.id = t1.id and t1.col1 >= t2.col1
);
Another solution:
SELECT DISTINCT ON (id) *
FROM (
SELECT *
FROM table1
UNION ALL
SELECT *
FROM table2
) AS aux
ORDER BY id, col1 DESC;
I tried it in Postgresql.

Hadoop - Hive - Impala - rewrite a query for performance

I have 2 tables with below columns
Table1
col1 col2 col3 val
11 221 38 10
null 90 null 989
78 90 null 77
table2
col1 col2 col3
12 221 78
23 null 67
78 90 null
I want to join these 2 tables first on col1 if values matched then stop if not join on col2 if matches stop else join on col3 and populate val if any of column matches else null and whichever columns matching then populate that column in matchingcol column. So, the output should look like this:
col1 col2 col3 val matchingcol
11 221 38 10 col2
null 90 null null null
78 90 null 77 col1
I was able to do this using below query, but the performance is very slow. Please let me know if there is any better way of writing below for faster performance
select *
from table1 t1 left join
table2 t2_1
on t2_1.col1 = t1.col1 left join
table2 t2_2
on t2_2.col2 = t1.col2 and t2_1.col1
left join table2 t2_3 on t2_3.col3 = t1.col3 and t2_2.col2 is null
ps: I asked same question before but there was no better answer
What you describe is:
select t1.col1, t1.col2, t1.col3,
(case when t2_1.col1 is not null or t2_2.col1 is not null or t2_3.col1 is not null then t1.val end) as val
(case when t2_1.col1 is not null then 'col1'
when t2_2.col2 is not null then 'col2'
when t2_3.col3 is not null then 'col3'
end) as matching
from table1 t1 left join
table2 t2_1
on t2_1.col1 = t1.col1 left join
table2 t2_2
on t2_2.col2 = t1.col2 and t2_1.col1 is null left join
table2 t2_3
on t2_3.col3 = t1.col3 and t2_2.col2 is null;
This is probably the best approach.

Select Group data with one matching condition

Table:
Col1 Col2
1 2
1 3
1 4
2 2
2 3
first need to check all rows with col2 = 4
Then need to select all rows with values col1
The result should be:
1 2
1 3
1 4
Off the top of my head
SELECT A.* FROM MyTable A JOIN MyTable B ON A.Col1 = B.Col1 WHERE B.Col2 = 4
I think you want this:
select t.*
from t
where t.col1 in (select t2.col1 from t t2 where t2.col2 = 4);
This query checks on both columns, where col2 = 4 and col1 = 1, from what i can understand in your description.
SELECT t1.col1, t2.col2 FROM Table t1
WHERE t1.col2 = 4
UNION
SELECT t2.col1, t2.col2 FROM Table t2
WHERE t2.col1 = 1

SQL Join with 2 columns when one of them is NULL/Blank

Let's say I have 2 tables like this:
I want to join both #tmp1 & #tmp2 for Columns : Col2 & Col3 . But if the value of either of these columns is blank or Null, I want to ignore that column and just look at one.
So for example here, when I join where Col2 is ABC, I should get both DEF & Blank for Col3.
I hope I'm making some sense here. Apologize if it's not clear enough.
I can't tell from your example what columns you want to join but to solve the "null" problem you do it like this
SELECT *
FROM T1
JOIN T2 ON COALESCE(T1.COL1,T2.COL1) = T2.COL1
AND COALESCE(T1.COL2,T2.COL2) = T2.COL2
If T1.COL1 or T1.COL2 are null it will use the value of the table it is joining to. This allows null to be a "wildcard".
or if T2 is the table with nulls
SELECT *
FROM T1
JOIN T2 ON T1.COL1 = COALESCE(T2.COL1,T1.COL1)
AND T1.COL2 = COALESCE(T2.COL2,T1.COL2)
You can use union for this checking if at least 1 of the 2 columns is the same using exists:
select col1, col2, col3
from tmp1 t1
where exists (select 1
from tmp2 t2
where t1.col2 = t2.col2 or t1.col3 = t2.col3)
union
select col1, col2, col3
from tmp2 t2
where exists (select 1
from tmp1 t1
where t1.col2 = t2.col2 or t1.col3 = t2.col3)
Fiddle Demo
Results:
| col1 | col2 | col3 |
|-------|------|------|
| test1 | abc | def |
| test2 | aaa | bbb |
| test1 | abc | |
| test2 | ccc | bbb |

Ordering in Access SQL

I don't know how to order the following data in Access SQL:
Col1 Col2
1 1
1 2
1 3
2 4
2 5
2 6
3 7
3 8
3 9
Where it grabs the lowest value in Col2 where Col1 = 1, and then the lowest value in Col2 where Col1 = 2 etc, leading to sorted data of:
Col1 Col2
1 1
2 4
3 7
1 2
2 5
3 8
1 3
2 6
3 9
Col1 can range from 1 to any number, and Col2 doesn't start from 1, or is consistently incremental (but still in the order of size).
The table also has an auto ID primary key if that helps.
---- Thanks to #shA.t this answer works perfectly. I added a simple table join which works as well:
SELECT t1.Col1, t1.Col2 FROM
(SELECT Table1.Col1, Table2.Col2 FROM Table2 INNER JOIN Table1 ON Table2.ID = Table1.ID) t1
INNER JOIN
(SELECT Table1.Col1, Table2.Col2 FROM Table2 INNER JOIN Table1 ON Table2.ID = Table1.ID) t2
ON t1.Col1 = t2.Col1 and t1.Col2 >= t2.Col2
Group by t1.Col1, t1.Col2
ORDER BY Count(t2.Col2), t1.Col1
I think you can use a query like this:
SQLFIDDLE DEMO
SELECT t1.Col1, t1.Col2
FROM t t1
JOIN t t2 ON t1.Col1 = t2.Col1 and t1.Col2 >= t2.Col2
Group by t1.Col1, t1.Col2
ORDER BY Count(t2.Col2), t1.Col1;