SQL left outer join to a min value of right table - sql

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

Related

if conditions inside where sql

I'm trying this logic not sure what am missing in this case
select *
from table1 t1
join table2 t2 on t1.column1=t2.column1
where t1.column1 between 1 and 10 if t2.column2='value1'
and t1.column1 between 11 and 20 if t2.column2='value2'
You could use a case when aproach
CREATE tABLE table2(column1 int, column2 varchar(10))
INSERT INTO table2 VALUEs(1,'value1'),(2,'value1'),(13,'value2'),(44,'value2')
CREATE tABLE table1(column1 int)
INSERT INTO table1 VALUES (1),(2),(13),(44)
select *
from table1 t1
join table2 t2 on t1.column1=t2.column1
where
CASE WHEN t1.column1 between 1 and 10 AND t2.column2 like 'value1' THEN TRUE
WHEN t1.column1 between 11 and 20 AND t2.column2 like 'value2' THEN TRUE
ELSE FALSE END
column1 | column1 | column2
------: | ------: | :------
1 | 1 | value1
2 | 2 | value1
13 | 13 | value2
db<>fiddle here
I assume you've left out key details, like the ON for the JOIN and the wildcard for the LIKE, in the interest of simplicity.
select *
from table1 t1
join table2 t2
where (t1.column1 between 1 and 10 and t2.column2 like 'value1')
or (t1.column1 between 11 and 20 and t2.column2 like 'value2')

Query for finding duplicate records where 2nd field is different

Probably very simple but given data of
TableA
FIELD1 | FIELD2
A | 1
A | 1
A | 2
B | 3
B | 3
C | 4
C | 5
How can I find the duplicate of Field 1 where Field 2 is different.
e.g from data above I want to return records 3 (A2) and 6 (C5)
Thanks in advance
You can use the following:
SELECT t1.* FROM table_name t1 INNER JOIN (
SELECT FIELD1, MIN(FIELD2) AS FIELD2
FROM table_name
GROUP BY FIELD1
) t2 ON t1.FIELD1 = t2.FIELD1 AND t1.FIELD2 <> t2.FIELD2
demo on dbfiddle.uk
You can use exists:
select a.*
from tableA a
where a.field2 > (select min(a2.field2)
from tableA a2
where a2.field1 = a.field1
);
You could also use window functions:
select a.*
from (select a.*,
min(a.field2) over (partition by field1) as min_field2
from tableA a
) a
where field2 > min_field2;

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 |

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 |

Comparing two tables with 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)