Displaying profile_name from friends table - mysql

I am trying to display the profile name of a user's friend. I have a friends table (users table) and the myfriends table (friend table). Don't ask why the stupidly confusing names, it is what the assignment requires. Ill refer as the friendsID as user_id and myfriendsID as friends_ID just to eliminate confusion.
Now, so far I have got it to list the user_id and the friends associated with that ID.
I want it to be able to also display the friends names through a profile_name I have on the user_id table.
The SQL i have at the moment is:
SELECT friends.friend_id, myfriends.friend_id2, friends.profile_name
FROM friends
INNER JOIN myfriends
ON friends.friend_id = myfriends.friend_id1
WHERE friends.friend_id = '2'
Problem is, is that it lists the name of the USER_ID, not the friend_id. The profile names I am trying to obtain are also from the user_id table, but with their own unique user_id. If that makes sense?

Join back to friends/users again.
Inner join friends as f2
On f2.friend_id = myfriends.friend_id1

Related

SQL Query JOIN with 4 tables

Who can help me?
I have 4 tables posts, users, users details and comments.
Here is the strucutre:
posts
id
title
description
users
id
username
password
users_details
id
user_id
avatar
location
comments
id
post_id
user_id
parent
comment
posted
I have a query which i want to display comments on specific post.
This is what i written but avatar column it doesn't show any results. It seems i written it wrong on join or something.
SELECT comments.id as comment_id,
comments.user_id as user_id,
comments.post_id as post_id,
comments.parent as parent,
comments.comment as comment,
comments.posted as posted,
users_details.avatar as avatar,
users.username as username
FROM `comments`
LEFT JOIN users ON users.id = comments.user_id
LEFT JOIN users_details ON users_details.user_id = users.id
WHERE comments.post_id='60337'
ORDER BY posted ASC
Here is a screenshot of the table with results https://i.imgur.com/VQ8KwV1.png
I want to mention the avatar field it has a value for that user in users_details table so it should be displayed...
Thanks!
Two potential reasons I could tell causing this issue.
1. The users do not have an avatar.
Try: Select Avatar from Users_Details where User_Id in (2,9212) and make sure it returns some data.
2. The Primary/Foreign key being used for joining the tables is not matching
Run those queries below and ensure that they are returning the same users.
select * from users where id in (2,9212)
select * from users_details where user_id in (2,2912)

Searching multiple rows that are not in a relationship n:m

Similar question here
Very similar to the question above but with a slight difference, I need to find a list of users that haven't seen at least one film in a list of movies.
Assuming two tables 'movies' and 'users', there's an n:m relationship between those, and a table 'seen' describing that relationship.
I need to find out for any number of given users, and any number of given movies all the users, from that given list, that have not watched at least one of the given movies.
Is this achievable in a single query? I can't figure out a way of do that.
Edit: Here's a demo with an attempt to solve the problem, the issue with that is it returns users that not have seen all of the movies from the given list. What we need is a user that has not seen ANY of the movies from that list: http://rextester.com/DEIH39789
This query should give you your desired result. I'm assuming your basic structure is:
users (id int, name varchar(20));
movies (id int, title varchar(20));
seen (user_id int, movie_id int);
SELECT u.*
FROM users u
LEFT JOIN seen s
ON s.user_id = u.id AND s.movie_id IN (movielist)
WHERE s.user_id IS NULL AND u.id IN (userlist)
The WHERE s.user_id IS NULL condition means the LEFT JOIN gives you all the users who have not seen any of the movies in movielist, and the u.id IN (userlist) then restricts the results to only that set of users.
You would modify the IN clauses to match the list of movies and users you were interested in. I've made a small demo on Rextester.
Update
I had misinterpreted the question; the desired result is for users who have not seen one (or more) of the movies in the list. This query solves that problem:
SELECT u.*
FROM musers u
LEFT JOIN seen s
ON s.user_id = u.id AND s.movie_id IN (1, 2)
WHERE u.id IN (1, 2, 3)
GROUP BY u.id
HAVING COUNT(s.movie_id) < 2
The result of the JOIN and WHERE is users (1, 2, 3) and the movies they have seen. If they have seen all of the movies in the movie list (1, 2), the COUNT of movies in seen will be 2, otherwise, if they have not seen one (or more) it will be less than 2. Here's an updated demo. Note that when the length of the movie list changes, the 2 in the HAVING clause must change to match the length of the movie list.
considering a n:m relationship between Users and Movies table, with intermediate table Seen.
SELECT * FROM Users u WHERE NOT EXISTS (SELECT UserId FROM Seen s WHERE s.UserId = u.ID)
this query will return Users which does not have any related record in Seen table
I would say something like a left-joining the users-table to the seen-table (and join that table to the movies-table).
(edited the code due to a comment from MatBailie)
Add the list-restritctions in the JOIN-clause (and not the WHERE-clause as MatBailie pointed out to me) and you get something like (Code below should work on SQL-Server but something similar should work for MySql as well):
SELECT COUNT(Users.ID)
FROM Users
LEFT JOIN Seen ON Users.ID = Seen.UserID AND Users.something IN (list)
LEFT JOIN Movies ON Seen.MovieID = Movie.ID AND Movies.something IN (list)
WHERE Movies.ID IS NULL
GROUP BY User.ID -- <-- This is probably optional
But as there are usually multiple ways to get the same result, the adjusted version of my previous answer:
SELECT COUNT(Users.ID)
FROM Users
LEFT JOIN Seen ON Users.ID = Seen.UserID
LEFT JOIN Movies ON Seen.MovieID = Movie.ID
WHERE (Users.something IN (list) OR Users.something IS NULL)
AND (Movies.something IN (list) OR Movies.something IS NULL)
AND Movies.ID IS NULL
GROUP BY User.ID -- <-- This is probably optional
Third attempt: Get all user-ids in list that have seen one of the movies. Next, get all user-ids in list and subtract the user-ids that have seen one of these movies. Know that for large data sets (a couple of thousand is not large) this query might become slow. To test it I've removed "userid = 2 and movieid = 3" from the list of seen, else I would not get a result. Now I see that Nick has not seen any of the first three movies (referring to your rextester example)
SELECT *
FROM musers
WHERE musers.id IN (1,2,3)
AND musers.id NOT IN (
SELECT musers.id
FROM musers
JOIN Seen ON musers.ID = Seen.UserID
JOIN Movies ON Seen.MovieID = movies.ID
WHERE movies.id IN (1,2,3) )

Inner join column twice with different values

I am new to database design so if this is an inefficient design, please let me know. This is my first post here and if you have any tips on how I could describe it better, I would appreciate it.
The situation is as follows:
Users register and are able to review other users
I have a table "Users"
I have a table "Reviews"
The review table has the following columns:
ReviewID
UserID (of the person who wrote the review)
Review: The actual review in text
Reviewed_User_ID: The UserID of the person who got reviewed
My question is: How would I go about creating a join that displays the columns: Users.First_name, Review.review, first_name of reviewed person
It will then read like: Name - wrote review about - Name. Instead of Name - wrote review about - UserID
The inner join like this:
SELECT users.first_name, review.review, review.reviewed_user_id
FROM users
INNER JOIN review ON users.user_id = review.user_ID
Will show me the reviewed_user_id but I would like to add the first_name of that person aswell. Is this even possible?
Many thanks in advance for any help or suggestions!
Please try to use something like that
SELECT users.first_name
, review.review
, review.reviewed_user_id
, reviewed_user.first_name
FROM users
INNER JOIN review ON users.user_id = review.user_ID
INNER JOIN users reviewed_user ON review.reviewed_user_id = reviewed_user.user_id
in this case we add other join to table users from table review by field reviewed_user_id with alias reviewed_user

Better MySQL query?

Here's one example, I have a Car, User, Member, and Dealer tables. At the moment I'm trying to get the name of a dealer who owns a car by matching their userids up
Select userid, name FROM `User` WHERE userid IN
(SELECT userid FROM 'Car' WHERE userid in
(SELECT userid FROM `Member` WHERE userid IN
(SELECT userid FROM `Dealer`)))
This does what I want but I can't help feel there's a better way of doing it? Currently the userid in Car is a FK of the userid in Dealer which is a FK of the userid in Member which is a FK of the userid in User which stores the name.
Can I go straight to getting all the userid's and names of dealers who's id is in the Car table, whilst making sure they're actually a Dealer?
Basically your schema is a downstream schema
Users -> Members -> Dealer -> Car
Good thing is you made all the possible keys that you need here.
So to selct anything in any table just go down stream from Users for example for the data you want
Select * from `USER` u
where
dealer.user_id = car.user_id and
member.user_id = dealer.user_id and
u.user_id = member.user_id
The reason i went upstream in matching records is because we want to make as few matching operations as possible. As you can see user table is supposed to contain the maximum records. So i match with car table and get all the user_id where there is a match in dealer. similarly i go from dealer to member and then to user. this means all the records of users will be matched with a lot fewer records that they would have been if i went from users to members to dealer to car.
But this is not fool proof solution. it will depend on your data. because it may be a case where one user may have multiple cars, then it would be better to go downstream.
Use JOIN instead of subqueries to fetch the data.
Try this:
SELECT U.userid, U.NAME
FROM `User` U
INNER JOIN Car C ON U.userid = C.userid
INNER JOIN Member M ON C.userid = M.userid
INNER JOIN Dealer D ON M.userid = D.userid;

How to query multiple tables with a single query

I have three tables: user, friend_recommendation, and movie.
I would like to get the name of the person who recommended this movie to me, along with the movie information from the movie table, and the comment in the friend_recommendation table. How do I do this?
Assume that user table has name as an attribute, movie table has movie title as an attribute, and friend_recommendation has UID (user who recommends), FID (who is recommended), and COMMENT (what is the comment from UID to FID)
Is it even possible to do this in one query?
So three tables, essentially with these fields (greatly simplified):
users (userId, name)
movies (movieId, movieInfo)
recommendations (fromUserId, toUserId, movieId, comment)
SELECT fromUser.name, toUser.name, m.movieInfo, r.comment
FROM recommendations r
INNER JOIN movies m ON m.movieId = r.movieId
INNER JOIN users fromUser ON r.fromUserId = fromUser.userId
INNER JOIN users toUser ON r.toUserId = toUser.userId
WHERE r.toUserId = << my user id, or whatever your criteria are >>
Edit in response to the comments below: Also retrieving the name/details of the user the movie was recommended to is as simple as joining to the users table again. You can see in the JOINs that we select from users twice.