SQL - joining data - mysql

Is it possible to get 1 result where I require data from 3 tables.
First table: I will need to grab all the fields (1 row found by a primary key)
Second table: I will need to grab the field 'username' (connected to first table by 'master_id')
Third table: I will need to grab the latest added row with the associated master_id key (table has 'date', 'master_id', 'previous_name').

select top 1 first.*, second.username, third.*
from first
inner join second on first.id = second.master_id
inner join third on first.id = third.master_id
order by
third.date desc
As always there are dozens of ways to skin a cat, I'm not sure if this is optimized as the subquery methods, but it should work.

You can join the three tables together. Then, you can use a "filter" join to keep only the latest Table3 row:
select *
from Table1 t1
join Table2 t2
on t2.master_id = t1.master_id
join Table3 t3
on t3.master_id = t1.master_id
join (
select master_id
, max(date) as max_date
from Table3
group by
master_id
) as filter
on t3.master_id = filter.master_id
and t3.date = filter.max_date

You'll need a correlated subquery for that third table.
SELECT t1.*, username, date, previous_name
FROM FirstTable t1
INNER JOIN SecondTable t2 ON t1.master_id=t2.master_id
INNER JOIN
(SELECT master_id, date, previous_name
FROM ThirdTable AS t3_1
WHERE date = (
SELECT MAX(date)
FROM ThirdTable AS t3_2
WHERE t3_2.master_id=t3_1.master_id)) q1 ON q1.master_id=t1.master_id;
NOTE: Untested.

Related

Have a left join where duplicates in the second table is involved - MYSQL

Table 1:
user score
------------
A 1
B 2
Table 2:
user comment time
----------------------------
A good <timestamp 1>
A bad <timestamp 2>
B average <timestamp 3>
I want to join these two tables such that I get the below:
user score comment
-------------------------
A 1 good
B 2 average
As you can see I'll need to join the second table's comment based on the timestamp (the most recent timestamp). I tried
SELECT st.user as user,st.score,
case when v.comment is null then 'NA' else v.comment end as comment
FROM tale1
left JOIN (select distinct user,comment,max(time) from table2) v ON st.user=v.user
but this doesnt work.
You can join with a correlated subquery that filters on the latest timestamp:
select
t1.*,
t2.comment
from table1 t1
left join table2 t2
on t2.user = t1.user
and t2.time = (
select max(t22.time)
from table2 t22
where t21.user = t1.user
)
Side note: I am unsure that you do need a left join here (your sample data does not demonstrate that).
You only want one column from table2 so I recommend a correlated subquery:
select t1.*,
(select t2.comment
from table2 t2
where t2.user = t1.user
order by t2.time desc
limit 1
) as comment
from table1 t1;
This query will make optimal use of an index on table2(user, time desc, comment) -- alas, though, I think the desc is ignored in MySQL.

More rows after Left Join in MySQL

I've two tables, table1 contains 22780 rows. Now I left join table1 with table2 (which doesn't contain any duplicates) and I get 23588 rows.
SELECT * FROM Table1
left join Tabelle6 ON CAST(Table1.Customer AS Int) = table2.Customer
Why do I get more rows now? I only need every row from table1 once.
Edit: found my issue, table 2 does contain duplicates. But is there any way to join every row only once and ignore any further matches?
As the comment suggests, the easiest way to handle this would probably be to do SELECT DISTINCT to remove duplicates from your result set:
SELECT DISTINCT
t1.col1,
t1.col2,
t1.Customer,
...
FROM Table1 t1
LEFT JOIN Table2 t2
ON CAST(t1.Customer AS Int) = t2.Customer
But there is another option here. We could also join to a subquery which removes duplicate customers. This would ensure that no record from the first table gets duplicated from matching to more than one record in the second table.
SELECT *
FROM Table1 t1
LEFT JOIN
(
SELECT DISTINCT Customer
FROM Table2
) t2
ON CAST(t1.Customer AS Int) = t2.Customer

select from table based on select distinct from another table

the case is that I need to select a field distinct from table1 (no duplicates) and use the result as a key to select from another table2. And I need this to be in one query. Is this possible?!
table1: hID, hName, hLocation
table2: hID, hFrom, hTo, hRate, hRoomType, hMeals
I want to correct version of this query:
SELECT
*
FROM
table1
JOIN (
DISTINCT
hID
FROM
table2
WHERE
hRoomType = Double Room
ON table1.hID = table2.hID)
expected result: all hotels that offer Double Room thanks much –
thanks for help!
Your question is quite vague and confusing. Is this what you are looking for:
SELECT hID, name, location
FROM table2
INNER JOIN table1
ON table1.hID = table2.hID
GROUP BY table2.hID;
Here is a skeleton to achieve this:
SELECT
* -- Don't forget to list the requested fields instead of using `*`!
FROM (
-- This is the distinct list from table1
SELECT DISTINCT
id
FROM
table1 T1
) DT1
INNER JOIN table2 T2
ON T1.id = T2.reference_to_t1_id
Another solution if you don't want to retrieve any columns from table1:
SELECT
* -- Don't forget to list the requested fields instead of using `*`!
FROM
table2 T2
WHERE
-- Sais that get all record from table2 where this condition matches
-- at least one record
EXISTS (
SELECT 1 FROM table1 T1 WHERE T1.id = T2.reference_to_t1_id
)
For your tables and question
SELECT
hID, hName, hLocation
FROM
table1 T1
WHERE
EXISTS (
SELECT 1 FROM
table2 T2
WHERE
T1.hID = T2.hID
AND T.hRoomType = 'Double' -- Assuming that this is the definition of double rooms
)

UNION or JOIN for this query

I have a $member_id, there are 5 tables which this member details are stored in those tables in multiple rows.
For getting out this user data from those tables, I can use JOIN and UNION:
//Using JOIN:
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id LEFT JOIN table3 ON table2.id=table3.id AND table1.member_id = '$member_id'
//USING UNION
(SELECT a FROM t1 WHERE member_id = '$member_id')
UNION
(SELECT a FROM t2 WHERE member_id = '$member_id')
ORDER BY a LIMIT 10;
Which one is preffered? which one has the better performance? what's the true way while you want to get some information from many tables which are related with foreign keys?
If you need all columns in same row you should use join. For a row by column you should use union. This is the criteria. They are no secret.
Remember to use left joins if this column don't appear in all tables:
SELECT table0.id as a0, table1.id as a1, table2.id as a2, ...
FROM
(select '$member_id' as id from dual ) table0
LEFT outer join table1 ON table1.id=table0.id
Left outer JOIN table2 ON table1.id=table2.id
LEFT outer JOIN table3 ON table2.id=table3.id
Also, in union, you can tag each row:
//USING UNION
(SELECT 't1' as t, a FROM t1 WHERE member_id = '$member_id')
UNION ALL
(SELECT 't2' as t, a FROM t2 WHERE member_id = '$member_id')
ORDER BY a LIMIT 10;
If you have the same structure and want to remove duplicate rows you can use UNION otherwise it's better to use JOIN statement

sql left join with distinct correct?

I'm trying to do a join between tables 1 and 2 which have a 1 to many relationship.
table1 has the following fields
createdate
contact
tkey (surrogate key)
table2 has the following fields
tkey (primary key)
status
userfld1
description
I want to show all items in table2 with their corresponding items in table1 grouped by table2.userfld1
select distinct t2.userfld1, t2.status, t2.description, t1.createdate, t1.contact
from table2 as t2 left join table1 as t1
on t2.tkey = t1.tkey
group by t2.userfld1
is this correct?
No that's not correct, you can't select columns that aren't in the group by unless they are contained in an aggregate function. And I think what you are asking for doesn't even make sense. My best guess is that you mean ORDER BY, not GROUP BY:
SELECT DISTINCT t2.userfld1, t2.status, t2.description, t1.createdate, t1.contact
FROM table2 t2
LEFT JOIN table1 t1
ON t2.tkey = t1.tkey
ORDER BY t2.userfld1
Three other errors that I've fixed:
SELECT ... FROM not SELECT ... WHERE
You should join with a table, not a column.
You had no aliases after the table names, but later refer to these missing aliases.
I think what you're looking for is order by, not group by, and I also fixed your query:
select t2.userfld1, t2.status, t2.description, t1.createdate, t1.contact
where table2 t2 left join table1 t1
on t2.tkey = t1.tkey
order by t2.userfld1
Is this what you were looking for?