Comparing two tables with SQL - sql

I need a query to produce a compare table between two tables.
Something like this:
table_1:
col1 | col2 | col3
a | 1 | a_comment
b | 2 | b_comment
table_2:
col1 | col2 | col3
a | 3 | a_comment
c | 4 | c_comment
Query result:
col1 | table_1.col2 | table_2.col2 | col3
a | 1 | 3 | a_comment
b | 2 | NULL | b_comment
c | NULL | 4 | c_comment
Also, I need to keep the order, s.t. if x in col1 is before y in col1 in any of the tables it will also be before it in the query result.
I tried to do it with FULL JOIN but it duplicates col1 and col3.
Thank you!

select t1.col1, t1.col2, t2.col2, t1.col3
from table_1 t1
left join table_2 t2
on t1.col1 = t2.col1
and t1.col3 = t2.col3
union
select t2.col1, t2.col2, t1.col2, t2.col3
from table_2 t2
left join table_1 t1
on t2.col1 = t1.col1
and t2.col3 = t1.col3

Full join is ok i think, you just have to select not all but just what you want, like
SELECT ISNULL(table_1.col1, table_2.col1) col1, table_1.col2, table2.col2, ISNULL(table_1.col3, table_2.col3) col3
ISNULL might be called different depending on what database system u use

SELECT col1
, t1.col2
, t2.col3
, col3
FROM table1 t1
FULL OUTER JOIN table2 t2
USING (col1, col3)

Related

SQL query to group multiple values

Can you let me how to build sql query for the below requirement:
I have 2 tables:
Table A:
col1 | Col2
------------
1 | a
2 | b
Table B:
Col1 | Col2
-----------
1 | 10
2 | 20
a | 30
b | 40
I need output like this:
Col1 | Col2
------------
1,a | 10,30
2,b | 20,40
Can anyone one help me please. Thanks
You can use this:
SELECT CONCAT(t1.col1, ' , ', t2.col1) AS Col1, CONCAT(t1.col2, ' , ', t2.col2) AS Col2
from
(select t1.col1, t2.col2 from tableA t1, tableB t2
where t1.col1 = t2.col1) as t1,
(select t1.col1 as col3, t2.col1, t2.col2 from tableA t1, tableB t2
where t1.col2 = t2.col1) as t2
where t1.col1 = t2.col3;
SQL Fiddle here:
http://sqlfiddle.com/#!9/459ae69/25
SQL DEMO
SELECT CONCAT(CONCAT(A."Col1", ' , '), A."Col2") AS Col1,
LISTAGG(B."Col2", ', ') WITHIN GROUP (ORDER BY B."Col1") Col2
FROM TableA A
JOIN TableB B
ON A."Col1" = B."Col1"
OR A."Col2" = B."Col1"
GROUP BY CONCAT(CONCAT(A."Col1", ' , '), A."Col2")
;
OUTPUT
| COL1 | COL2 |
|-------|--------|
| 1 , a | 10, 30 |
| 2 , b | 20, 40 |

Merge columns and Sub Select list

My query simply looks like:
SELECT col1, col2,
(SELECT col3, col4 FROM Table2)
FROM Table1
Wanted result is:
col1 | col2 | col3 | col4
-------------------------
ABC | DEF | GHI | JKL
... | ... | ... | ...
But I am getting an error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
How to merge lists and current rows?
You probably want something like this:
SELECT col1,
col2,
(SELECT col3 FROM Table2 as t2 WHERE t2.id = t1.id) as col3,
(SELECT col4 FROM Table2 as t2 WHERE t2.id = t1.id) as col4
FROM Table1 as t1
or even better:
SELECT t1.col1,
t1.col2,
t2.col3,
t2.col4
FROM Table1 as t1
JOIN Table2 as t2
ON t1.id = t2.id
if you don't have a field to join both tables then:
SELECT t1.col1,
t1.col2,
t2.col3,
t2.col4
FROM Table1 as t1
CROSS JOIN Table2 as t2

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 |

SQL left outer join to a min value of right table

I have two tables, lets say table1 and table2.
table1 || table2
--------||-------------
col1 || col1 | col2
--------||------|------
a || a | 4
b || a | 2
c || a | 5
d || b | 1
|| b | 3
|| d | 6
With SELECT table1.col1, table2.col2 FROM table1 LEFT OUTER JOIN table2 ON table1.col1 = table2.col1 I get following:
table1.col1 | table2.col2
-------------|-------------
a | 4
a | 2
a | 5
b | 1
b | 3
c | NULL
d | 6
How is it possible to achieve this (only get the minimum of table2.col2 so that there's no entry of table1.col1 more than once):
table1.col1 | table2.col2
-------------|-------------
a | 2
b | 1
c | NULL
d | 6
Or is it a wrong approach?
You need to use MIN:
SELECT
t1.col1,
MIN(t2.col2) AS col2
FROM table1 t1
LEFT JOIN table2 t2
ON t2.col1 = t1.col1
GROUP BY t1.col1
SQL Fiddle
Alternative solution, use a correlated sub-query:
select col1, (select min(col2) from table2 t2 where t2.col1 = t1.col1)
from table1 t1
If there are more columns in table2 you may want to use APPLY operator:
SELECT * FROM table1
OUTER APPLY(SELECT TOP 1 * FROM table2
WHERE table1.col1 = table2.col1 ORDER BY table2.col2)oa

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;