Basic many-to-many left join query - mysql

So I have 3 tables:
users
achievements
achievements_unlocked (many-to-many)
I would like a query to return all achievements available, plus mention what achievements the current user (id_user=123 for example) has unlocked.
How can I do this? This should involve a LEFT JOIN but if I add "WHERE id_user = 123" it won't get me achievements locked...
Thanks!

Try this
SELECT ac.*,
CASE WHEN un.ach_id IS NULL THEN 0
ELSE 1 END AS user_unlocked
FROM achievements ac
LEFT JOIN
(SELECT au.ach_id FROM achievements_unlocked au
INNER JOIN users u ON au.user_id = u.id
WHERE u.id = 123) un
ON ac.id = un.ach_id

Select *
From achievements
Left Outer Join achievements_unlocked On achievements_unlocked.achievement_id = achievements.achievement_id
Left Outer Join users On
users.user_id = achievements_unlocked.user_id And
users.user_id = 123
This will likely be the most efficient way to do this without having to do nested loops and hash matching in the execution plan. Make sure you have indexes on the achievement_id and user_id columns on all tables that contain them.

Related

Joining 3 tables, not getting desired result

I have three tables in MySql:
Events, Users both having many to many relation. Hence, third table Attend.
Table content:
Events:
e_id, e_content
Users
u_id, u_details
Attend
e_id, u_id, attending
let consider I am logged in and my uid is 1005.
So I want to see all events whether or not I am attanding the evnet but if I am attending the Attend.attending column should be yes else it should be null
I have tried a lot with joins but I have not received the desired query.
like:
select e.e_id,u.u_details,a.attending
from Events e
left join attend a on e.e_id = a.e_id
left join users u on u.u_id = a.U_id
and u.u_id = 1005;
with the above query I get same result for all uid
You need to do a LEFT JOIN here like
select e.e_id,u.u_details,a.attending
from Events e
left join attend a on e.e_id = a.e_id
left join users u on u.u_id = a.U_id
and u.u_id = 1005;
If, as is specifically asked, all events require displaying, but just where a particular user (1005) is attending has attending = "Yes" then is requires a little more than left joins, as if multiple users are attending, it will still display "Yes" for all users attending, even though the u_id is not displayed.
http://sqlfiddle.com/#!9/ed738/3/1
Shows the query with 2 left joins, and then the 2nd result set which gets what I believe is the required result.
select e.e_id,a.u_details,a.attending
from Events e
left join (select a.*, u.u_details
from attend a
INNER join users u ON
(a.u_id = u.u_id and u.u_details = 'will')) a on e.e_id = a.e_id
There are more than likely more elegant ways of doing this, but think this does the job.

Join two tables query

I have two tables users and linkage. I am creating a link between one user to another. Means user A will be linked to user B and vise versa.
Now I want to get the details of linked users for a particular entered user_id. Means If user A is finding his linked Id's then the details of linked id's should be seen.
Linkage has three columns its id, user_id and linked_contact_id.
Users has columns as user_id, user_name,pass etc..
I tried one join but I only get the linked Id's from this not the details of id's.
SELECT * FROM Users INNER JOIN linkage ON linkage.user_id = Users.user_id WHERE linkage.linked_contact_id = 1
output
user_id linked_contact_id
1 4
1 1
1 5
How can I get this?Please help.. Thank you...
You will need to join on the users table a second time:
SELECT u.*, u2.* FROM Users u
INNER JOIN linkage l ON l.user_id = u.user_id
INNER JOIN Users u2 ON l.linked_contact_id = u2.user_id
WHERE l.linked_contact_id = 1
Please note that as you are selecting the same columns twice (in u.*, u2.*), you will probably have to list out each field with an alias to distinguish between them.
Something wrong on your ratio. But it's okay.
Try LEFT JOIN or RIGHT JOIN
SELECT * users
LEFT JOIN linkage
ON linkage.user_id = users.user_id
WHERE linkage.linked_contact_id = 1
Get Users information
SELECT users.*,
linkage.*,
contact.user_id as contact_user_id,
contact.user_name AS contact_user_name
FROM users
INNER JOIN linkage ON linkage.user_id = users.user_id
INNER JOIN users AS contact ON linkage.linked_contact_id = contact.user_id
WHERE linkage.linked_contact_id = 1
Edit
Here Screenshot of Query Output

Find unique values that do not exist in multiple columns and tables

A misconfigured manual import imported our entire AD into our help desk user database, creating a bunch of extraneous/duplicate accounts. Of course, no backup to restore from.
To facilitate the cleanup, I want to run a query that will find users not currently linked to any current or archived tickets. I have three tables, USER, HD_TICKET, and HD_ARCHIVE_TICKET. I want to compare the ID field in USER to the OWNER_ID and SUBMITTER_ID fields in the other two tables, returning the only the values in USER.ID that do not exist in any of the other four columns.
How can this be accomplished?
Do a left join for each relationship where the right table id is null:
select user.*
from user
left join hd_ticket on user.id = hd_ticket.owner_id
left join hd_ticket as hd_ticket2 on user.id = hd_ticket2.submitter_id
left join hd_archive_ticket on user.id = hd_archive_ticket.owner_id
left join hd_archive_ticket as hd_archive_ticket2 on user.id = hd_archive_ticket2.submitter_id
where hd_ticket.owner_id is null
and hd_ticket2.submitter_id is null
and hd_archive_ticket.owner_id is null
and hd_archive_ticket2.submitter_id is null
How about something like:
SELECT id
FROM user
WHERE id NOT IN
(
SELECT owner_id
FROM hd_ticket
UNION ALL
SELECT submitter_id
FROM hd_ticket
UNION ALL
SELECT owner_id
FROM hd_archive_ticket
UNION ALL
SELECT submitter_id
FROM hd_archive_ticket
)
If I understood you situation I would do this:
SELECT a.id FROM user a, hd_ticket b, hd_archive_ticket c WHERE a.id != b.id AND a.id != c.id
You would want to try something like below. Inner query where I am doing Inner join with other 2 tables, will return only those user id which exist in all 3 tables. Then in your outer query I am just filtering out those ID's returned by inner query; since your goal is to get only those USER ID which is not present in other tables.
select ID
FROM USER
WHERE ID NOT IN
(
select u.ID
from user u
inner join HD_TICKET h on u.ID = h.OWNER_ID
inner join HD_ARCHIVE_TICKET ha on u.ID = ha.SUBMITTER_ID
)

SELECT different users from same table in single JOIN

I am currently trying to join a table (tasks) with another table (users). I need to select different rows from the users table based on values in the tasks table:
tasks(user1, user2, user3);
users(id, name, email);
Previously I have linked data using a LEFT JOIN like so:
SELECT * FROM tasks LEFT JOIN users ON tasks.user1 = users.id;
Thats pretty simple, so I have tried using an AND like so:
SELECT * FROM tasks LEFT JOIN users ON tasks.user1 = users.id AND tasks.user2 = users.id;
but that returns the users fields as NULL, which makes sense as tasks.user1 is different to tasks.user2
I am pretty stumped on how to do this now, all suggestions welcome!
You'll need to repeat the join and alias the users table diffeently for each joined column:
SELECT * FROM tasks
LEFT JOIN users u1 ON tasks.user1 = u1.id
LEFT JOIN users u2 ON tasks.user2 = u2.id
...
use this one:
SELECT *
FROM tasks
LEFT JOIN users
ON tasks.user1 = users.id
OR tasks.user2 = users.id;

Need an alternative to two left joins

Hey guys quick question, I always use left join, but when I left join twice I always get funny results, usually duplicates. I am currently working on a query that Left Joins twice to retrieve the necessary information needed but I was wondering if it were possible to build another select statement in so then I do not need two left joins or two queries or if there were a better way. For example, if I could select the topic.creator in table.topic first AS something, then I could select that variable in users and left join table.scrusersonline. Thanks in advance for any advice.
SELECT * FROM scrusersonline
LEFT JOIN users ON users.id = scrusersonline.id
LEFT JOIN topic ON users.username = topic.creator
WHERE scrusersonline.topic_id = '$topic_id'
The whole point of this query is to check if the topic.creator is online by retrieving his name from table.topic and matching his id in table.users, then checking if he is in table.scrusersonline. It produces duplicate entries unfortunately and is thus inaccurate in my mind.
You use a LEFT JOIN when you want data back regardless. In this case, if the creator is offline, getting no rows back would be a good indication - so remove the LEFT joins and just do regular joins.
SELECT *
FROM scrusersonline AS o
JOIN users AS u ON u.id = o.id
JOIN topic AS t ON u.username = t.creator
WHERE o.topic_id = '$topic_id'
One option is to group your joins thus:
SELECT *
FROM scrusersonline
LEFT JOIN (users ON users.id = scrusersonline.id
JOIN topic ON users.username = topic.creator)
WHERE scrusersonline.topic_id = '$topic_id'
Try:
select * from topic t
left outer join (
users u
inner join scrusersonline o on u.id = o.id
) on t.creator = u.username
If o.id is null, the user is offline.
Would not it be better to match against topic_id in the topics table by moving the condition to the join. I think it will solve your problem, since duplicates come from joining with the topics table:
SELECT * FROM scrusersonline
JOIN users
ON users.id = scrusersonline.id
LEFT JOIN topic
ON scrusersonline.topic_id = '$topic_id'
AND users.username = topic.creator
By the way, LEFT JOIN with users is not required since you seem to search for the intersection between scrusersonline and users