Which MySQL JOIN and How...? - mysql

I have two tables:
Table 1 contains the User ID
Table 2 contains the user ID and other data I would like
The relationship is on the ID in both tables so what I would like to do is the following:
Pull all data from table 2 where a record exists in the id field in table 2 that matches an id in table 1.
Table 1 has other copies so to speak that are specific to other accounts while table 2 contains all the ids for all the other tables which is why (I think) I need a JOIN statement but I'm open to suggestions.
Table 1:
id
123456
Table 2:
id | name | age
123456 | John | 23
651123 | Mary | 22
811561 | Sarah | 21

You can use subquery as:
SELECT *
FROM table2
WHERE ID IN (SELECT ID
FROM table1)
If you need fields from table1 as well then use an inner join like:
SELECT t1.*, t2.name, t2.age
FROM table1 t1 INNER JOIN table2 t2
ON t1.id = t2.id

Your assumption is correct, you need to join:
Select * from table1 inner join table2 on table1.userid = table2.userid
The only question here is if you want to get only id's that appear on both tables (and than use inner join) or also get such that appear only on the first table as well (left join)

You should choose inner join here because table 2 always contain records for table 1.

You can use INNER JOIN here becuase you have relation between both table, query should be this:
SELECT t1.id, t2.name, t2.age
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id

Related

sql join request

Well, i'm trying to make a sql request with join but i don't know how to do it.
Here my first table - Table 1
id
postid
user
My second table - Table 2
id
title
Postid and id are the same.
i've done a screenshot of my table 1
As you can see, there are many entries with postid 32. This is totally normal.
I want to do a sql request on this 2 tables.
The results expected have to be like this :
Title of id 31 (from table 1) - 2 (because there are 2 entries with postid 31 in table 2)
Title of id 32 (from table 1) - 23 (because there are 23 entries with postid 32 in table 2)
Someone can help me ?
Try this:
select t1.postid, count(t2.id)
from Tab1 t1 join Tab2 t2
on t1.postid = t2.id
group by t1.postid;
Here the name of the tables are Tab1 and Tab2 and they have aliases t1 and t2.
If you are interested only in the postids of table1 then there is no need for a join:
select postid, count(*)
from table1
group by postid;
If you want to count all the ids of table2 even the ones that are missing in table1 then you need a left join:
select t2.id, count(t1.postid)
from table2 t2 left join table1 t1
on t1.postid = t2.id
group by t2.id;

MySQL inner join with multiple columns

Let's say I have the following table called Email, where Id is the primary key:
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | anne#example.com |
| 2 | cat#example.com |
| 3 | anne#example.com |
+----+------------------+
I'm trying to delete all occurrences of duplicates except the first. So in this case the desired output would be
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | anne#example.com |
| 2 | cat#example.com |
+----+------------------+
After asking a friend, I found this solution works:
DELETE t1 FROM Person t1 INNER JOIN Person t2
Where t1.Email=t2.Email and t1.Id > t2.Id
My question is why does this work? In particular, when t1 inner joins t2 on Email field, how does the program know which row of anne#example.com should be matched with which, since there are multiple occurrences of this value with different Ids?
Consider this select statement only filtering by equality among email columns
SELECT t1.*, t2.*
FROM Person t1
INNER JOIN Person t2
WHERE t1.Email=t2.Email
ORDER BY t1.Id, t2.Id;
returns (1,1), (1,3), (3,1), (3,3) for t1.id and t2.id values respectively for the mail anne#example.com, and only (2,2) for cat#example.com. Then If you consider the other filter AND t1.Id > t2.Id,
SELECT t1.*, t2.*
FROM Person t1
INNER JOIN Person t2
WHERE t1.Email=t2.Email
AND t1.id > t2.id
ORDER BY t1.Id, t2.Id;
then you'll only have one tuple (3,1) since t1.id > t2.id is satisfied only for this case of id tuples. If you convert SELECT t1.*, t2.* to DELETE t1 (of course remove ORDER BY part also), then obviously you'll delete id = 3 and left rows with id values 1 and 2, reversely if you replace SELECT t1.*, t2.* with DELETE t2, then you'll have rows with id values 2 and 3.
Demo
First, this is more commonly written using aggregation:
DELETE p
FROM Person p INNER JOIN
(SELECT p2.email, MIN(p2.id) as min_id
FROM Person p2
GROUP BY p2.email
) p2
ON p.email = p2.email and p.id > p2.min_id;
Why does your version work? Well, it works because of the fact that a join not only matches data but also filters data.
So, the condition
t1.Email = t2.Email and t1.Id > t2.Id
Says that for each record in t1 find matching records in t2 where t1.id > t2.id. That is, find records in t1 that have a matching record with a smaller id.
All records have this property -- except for one for each email. That would be the record with the smallest id.
I do not recommend this method for identifying the smallest record, because the join multiplies the number of records. If one email has five records, then there are up to four matches for one of the records. MySQL needs to figure out what to do when you say to delete a single record four times. (It does the right thing, of course, but there is extra work.)
The aggregation method doesn't have any issues like this.
You compare two identical tables and check all occurrences where emailaddress of both tables are identical.
if the id is the same, the row is ignored.
If the id is different and it must have an id that is bigger than the id of first occurrence , this row gets deleted.

MySQL join three table

I have three table
table1
userid name
1 A
2 B
3 C
table2
trackid userid track_des
1 2 123
2 3 234
3 3 345
table3
trackid description
1 ABC
2 BCD
I want output like this where userid=3
userid name trackid description track_des
3 C 2 BCD 234
3 C 3 NULL 345
I am using MySQL.
Your table1 looks to contain users and your table3 looks to contain tracks. Your table2 looks like it's a join table describing a many-to-many relationship between users and tracks. It seems the join table may contain references to tracks that don't exist in table3 eg. trackid 3. To produce the output you've shown in your example, begin by selecting the records corresponding to userid 3 and join it to table2 (your many-to-many join table). Next, you should left join to your table containing tracks. You need a left join here because some tracks listed in the join table won't be found but those rows should still be included in the output. The only task remaining is specifying the columns you would like returned. Here is what the complete query looks like:
select
u.*,
ut.trackid,
t.description,
ut.track_des
from table1 as u
inner join table2 as ut
on ut.userid = u.userid
left outer join table3 as t
on t.trackid = ut.trackid
where u.userid = 3;
select
t1.*,
t2.trackid,
t3.description,
t2.track_des
from table1 as t1
inner join table2 as t2
on t2.userid =t1.userid
left join table3 as t3
on t3.trackid = t2.trackid
where t1.userid = 3;

how to make query show the an other column of the primary key?

umm I'm not sure I've made the title right but its kind of hard to express it in short words.
I have to tables
table1:
id | name
1 | alice
2 | bob
table 2:
user_id | date
2 | 2014-11-1
2 | 2014-11-2
1 | 2014-11-3
as a query, if I want to show table 2 but instead of the integer numbers of user_id, I want it to show the corresponding names of the users where this info is stored in table 1.
I think this is supposed to be easy but I don't know how to get this done.
A query along the lines of -
select t1.name, t2.date
from table_1 t1 inner join table_2 t2 on t1.id = t2.user_id
Try:
SELECT t2.user_id, t1.name
FROM table1 t1 INNER JOIN table2 t2
ON t1.id = t2.user_id
This will do it.
SELECT
`b`.`name`,
`a`.`date`
FROM
table2 a
INNER JOIN table1 b ON (a.user_id = b.id)
SELECT
B.[Name]
,A.[date]
FROM [table 2] A
LEFT OUTER JOIN [table1] B
ON A.[user_id] = B.[id]

MySQL Query same column twice

I have two tables one with ID and NAME
table 1
ID | NAME
1 | first
2 | second
3 | third
and an XREF table with ID and PARENT ID
table2
ID | PARENT ID
1 | 0
2 | 1
3 | 2
and I would like to retrieve the NAME twice like this: NAME | PARENT NAME
If it is possible to go three levels deep but with same 2-column table like this:
result table
NAME | PARENT NAME
first | NULL or EMPTY or this line the not showing at all
second | first
third | second
... then I'd like to figure that out as well.
select t1.Name, t12.Name from
table1 t1
inner join table2 t2 on t1.ID = t2.ID
inner join table1 t12 on t2.ParentID = t12.ID
This would only return 2 rows. If you want to have the first row (for ID=1) you just need to outer join instead.
Consider putting the parentid in the first table as a self-referential relationship rather than having a separate table for it.
Ex.:
table1
ID | PARENTID | NAME
---------------------------
1 NULL first
2 1 second
3 2 third
That way you would only need to join the table on itself rather than going through a 3rd table. (This is however assuming that the rows in table1 can only have a single parent, whereas your design allows one row to have multiple parents at a time)
But for your table structure, this will work:
SELECT
a.name,
c.name AS 'PARENT NAME'
FROM
table1 a
LEFT JOIN
table2 b ON a.id = b.id
LEFT JOIN
table1 c ON b.parentid = c.id
But if you made the parentid in the same table referencing id, the SQL would be reduced to this:
SELECT
a.name,
b.name AS 'PARENT NAME'
FROM
table1 a
LEFT JOIN
table2 b ON a.parentid = b.id