Distinct SQL Join two tables - sql

I am trying to join two tables such that I am getting only a first match from the Right table instead of every match in Table2.
So if the query is:
SELECT T1.Name, T2.Dates
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.ID = T2 = ID
WHERE T1.Name = 'John'
I would like to see
John | 14/11/14
Joe | 10/10/2014
Jane | 25/10/2014
Instead of
John | 14/11/2014
John | 12/10/2014
Joe | 10/10/2014
Jane | 25/10/2014
Jane | 26/10/2014
Which join should I use?

You need to decide which row, you should select. Min or max as commented.
SELECT T1.Name,
( SELECT MIN( T2.Dates) FROM Table2 T2 WHERE T1.ID = T2 = ID) AS Dates
FROM Table1 T1
WHERE T1.Name = 'John'

The ANSI standard function row_number() can be a big help here. It is supported by most databases, so you can do:
SELECT T1.Name, T2.Dates
FROM Table1 T1 LEFT JOIN
(SELECT t2.*, ROW_NUMBER() OVER (PARTITION BY t2.ID ORDER BY t2.DATE DESC) as seqnum
FROM Table2 t2
) T2
ON T1.ID = T2.ID AND seqnum = 1
WHERE T1.Name = 'John';
In your question, you have only one column from the second table, so you can also do this with aggregation:
SELECT t1.ID, t1.Name, MAX(t2.Date)
FROM Table1 T1 LEFT JOIN
Table2 T2
ON t1.ID = t2.ID
WHERE T1.Name = 'John'
GROUP BY t1.ID, t1.Name;

Query
SELECT a.name,
MAX(b.Dates)
FROM tbl1 a
JOIN tbl2 b
ON a.id=b.id
WHERE a.name='John'
GROUP BY a.name;
Demo

Related

sql - how to select multiple columns with only one distinct column from joining multiple tables

I am using SQL Server. I want to select multiple columns with only one distinct column.
For example,
TABLE 1:
ID NAME ...(other columns)
1 A
2 B
3 C
Table 2 (ID and number together is the unique key):
ID Number Year...(other columns)
1 111 2011
2 12345678 2011
2 22222222 2012
3 333 2013
Table 3:
Name Company ...(other columns)
A Amazon
B Google
C Amazon
Each table above has many columns (more than 2). How can get the result so that there are only 5 columns as result without other "useless" columns and the ID column is the distinct column.
More specifically, for example,
The normal sql statement I had is the following:
select distinct ID, NAME, NUMBER, COMPANY, Year
from table1
left join table2 on table1.ID = table2.ID
left join table3 on table1.name = table3.name
group by ID, NAME, NUMBER, COMPANY, year
order by ID desc, Year desc
This will output the following:
ID NAME NUMBER COMPANY YEAR
1 A 111 Amazon 2011
2 B 12345678 google 2011
2 B 22222222 google 2012
3 c 333 Amazon 2013
What I want to have is actually the following:
ID NAME NUMBER COMPANY YEAR
1 A 111 Amazon 2011
2 B 22222222 google 2012
3 c 333 Amazon 2013
I want to have the results without duplicated ID. If there are duplicate ID's, I want to show only the latest one. In above example, ID 2 has 2 rows in table2. I want to show the one with the latest date which is 2012.
How can I achieve this. Thanks in advance.
You can use not exists to only select the latest rows per id (where another row with the same id and a greater year does not exist).
select * from table1 t1
where not exists (
select 1 from table1 t2
where t2.id = t1.id
and t2.year > t1.year
)
using analytic functions (this should be faster than the query above)
select * from
(select *,
row_number() over(partition by id order by year desc) rn
from table1) t1 where rn = 1
edit: applied to your tables
select t2.id, t3.name, t2.number, t3.company, t2.year from
(
select * from
(select *,
row_number() over(partition by id order by year desc) rn
from table2
) t1 where rn = 1
) t2 join table1 t1 on t2.id = t1.id
join table3 t3 on t3.name = t1.name
WITH CTE AS
(
SELECT t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY, t2.Year,
Row_number() OVER(partition BY t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY ORDER BY t2.Year DESC) AS rn
FROM table1 t1
LEFT JOIN table2 t2 ON t1.ID = t2.ID
LEFT JOIN table3 t3 ON t1.name = t3.name
)
SELECT ID, NAME, NUMBER, COMPANY, Year
FROM CTE
WHERE rownum = 1
ORDER BY ID desc, Year desc
I used a subquery, note subqueries are inefficient.
select distinct t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY, t2.Year
from table1 t1
left join table2 t2 on t1.ID = t2.ID
inner join table3 t3 on t1.name = t3.name --inner join to select the latest record only
and t2.Year = (Select MAX(year) from table2 t22
where t22.ID = t2.Id group by ID)
group by t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY, t2.year
order by t1.ID, t2.Year desc
EDIT: using a more efficient CTE
WITH CTE as
(
Select Id, MAX(year) as [yr] from table2 t2 group by ID
)
select distinct t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY, t2.Year
from table1 t1
left join table2 t2 on t1.ID = t2.ID
left join table3 t3 on t1.name = t3.name
inner join CTE on cte.yr = t2.Year
and t2.Id = CTE.Id
group by t1.ID, t1.NAME, t2.NUMBER, t3.COMPANY, t2.year
order by t1.ID, t2.Year desc

select clause with having max condition

For my database table:
//table1
name
---------
john
mary
ali
in my table2
//table2
title
---------
test1
test2
test3
in my table3
//table3
name title
-----------------
john test1
john test2
john test3
mary test2
So my question is to find the title that been joined by name for most many times.
So my query is:
SELECT t2.title from table2 t2 inner join table3 t3 on
t2.title = t3.title inner join table1 t1 on
t1.name = t3.name having max(....)
as i check for some websites. all they use for the having clause is for the numbers only, i can't find any example that suit for my question that need to count(*)
expected output:
//result
title
---------
test2
Order by the count to get a list starting from the most common ttile
SELECT t2.title
from table2 t2
inner join table3 t3 on t2.title = t3.title
inner join table1 t1 on t1.name = t3.name
group by t2.title
order by count(*) desc
To get only the top result use
SELECT * FROM
(
SELECT t2.title
from table2 t2
inner join table3 t3 on t2.title = t3.title
inner join table1 t1 on t1.name = t3.name
group by t2.title
order by count(*) desc
) X
WHERE ROWNUM = 1;
SELECT max(name) KEEP(DENSE_RANK FIRST ORDER BY COUNT(NAME) DESC)
FROM table3
GROUP BY name

MSSQL join with itself

I have two tables:
id
1
2
3
4
t1 AND t2
id | related_id
1 | 2
1 | 3
Where t2 is relationship table between t1 records. What is the best way to get desired output?
t1.id | t1_copy.id
1 | NULL -- want to get this NULL row
1 | 2
1 | 3
Simple JOIN would almost work, however it doesn't give me the first NULL row.
SELECT t1.id, t1_copy.id FROM t1
LEFT JOIN t2 ON t1.id = t2.id
LEFT JOIN t1 t1_copy ON t1_copy.id = t2.related_id
WHERE t1.id = 1
P.S: Yes, I do realize that desired output is wacky.
Seems like a simple UNION should do the trick
SELECT
id,
null as copy_id
FROM
t1
WHERE
exists (select * from t2 where t1.id = t2.id)
UNION ALL
SELECT
t1.id,
t2.related_id
FROM
t1
INNER JOIN t2
ON t1.id = t2.id
SQL Fiddle
SELECT DISTINCT t1.id, t1_copy.id FROM t1
LEFT OUTER JOIN t2 ON t1.id = t2.id
WHERE t1.id = 1

Join sql results

Please, help me with join results of commands (MS SQL):
SELECT name,value FROM table1 WHERE idfoo1 IN(SELECT _id FROM table3 where id = 1);
SELECT value FROM table2 WHERE idfoo2 IN(SELECT _id_2 FROM table3 where id = 1) AND name='fooname';
And I get:
name value
John 2
Bill 32
Alex 11
value
434
234
144
But I need join results.
name value value
John 2 434
Bill 32 234
Alex 11 144
So, id == id, _id != _id_2,
Use this query:
SELECT t1.name,
t1.value,
t2.value
FROM table1 t1
INNER JOIN table3 t3 ON t1.idfoo1 = t3._id
INNER JOIN table2 t2 ON t2.idfoo2 = t3._id_2
WHERE t3.id=1 AND t2.name = 'fooname'
Select a.name,a.value,c.value FROM table1 as a inner join table3 as b
on a.idfoo1=b.id and b.id=1 inner join table3 as c
on c.idfoo2=b._id_2 and b.id=1 and c.name='fooname'
i guess this is what you need-
SELECT t1.name, t1.value, t2.value
FROM table1 t1, table2 t2, table3 t3
WHERE
t1.idfoo1 = t3._id
AND t2.idfoo2 = t3._id_2
AND t3.id = 1
AND t2.name='fooname';

MySQL: Union of a Left Join with a Right Join

Say we have the following tables t1 and t2:
t1:
id | column_1
-------------
1 | 1
2 | 2
t2:
id | column_2
-------------
2 | 2
3 | 3
and we want to find the following result:
id | column_1 | column_2
------------------------
1 | 1 |
2 | 2 | 2
3 | | 3
This basically is the union of a right join with a left join. The following code works but feels clumsy:
(
SELECT t1.id, t1.column_1, t2.column_2
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
)
UNION
(
SELECT t2.id, t1.column_1, t2.column_2
FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
)
Is there a better way to achieve this?
select a.id, t1.column_1, t2.column_2
from (
select id from t1
union
select id from t2
) a
left outer join t1 on a.id = t1.id
left outer join t2 on a.id = t2.id
Try this one:
SELECT t1.id, t1.column_1, t2.column_2
FROM t1
FULL OUTER JOIN t2 ON (t1.id = t2.id)
Edit: Doesn't work, MySQL does not know FULL OUTER JOIN.
Have a look here:
http://www.xaprb.com/blog/2006/05/26/how-to-write-full-outer-join-in-mysql/
Haven't tried this myself, but this might work:
SELECT t1.id, t1.column_1, t2.column_2, t2a.column_2
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
RIGHT JOIN t2 AS t2a ON t1.id = t2a.id