Multiple inner joins in MySql not working - php

I have 3 tables :
useractivitylog
id userid activity_type activity_id date
which will store all user activities.
requestfriend
opid userid friendid requesttime message source requesttype friendemail status
which will store friends details. userid and friendid can be the user's id. If user A has send friend's request to user B, then userid will contain the id of A and friendid will be the id of B. So anyway B is the friend of A and A is the friend of B.
auth_user_profiles
id user_id first_name last_name profileimage
which stores user profile information.
What I need is to select all my friends activities from useractivitylog table. I tried with the following query. But it didnt worked.
echo "select ua.*,rf.opid,aup.user_id,aup.first_name,aup.last_name,
aup.profileimage from useractivitylog as ua INNER JOIN requestfriend as rf
INNER JOIN auth_user_profiles as aup on
aup.user_id= IF (rf.userid='$userid',rf.friendid,rf.userid)
WHERE (rf.userid=$userid or rf.friendid=$userid)
and rf.status='2' and ua.userid!=$userid";
Here, $userid is my user id. Actually what I want is to retrieve the profile information and the activities of users who are friends of mine. But know, it is returning all rows in useractivitylog table even if the userid is not in my friends list.
Can anyone help me to find an appropriate query for this. Thanks in advance.

You don't join properly. The only condition for a useractivitylog being linked to the other tables is that its user ID is not $userid. That is true for most records in the table, so you almost get a cartesian product (cross join).
BTW: You don't join auth_user_profiles properly either, because you compare with the string '$userid' instead of comparing with $userid.
Let's re-write the statement such that we retrieve the friends first and join the other tables with these:
select
ua.*,
friend.opid,
aup.user_id,
aup.first_name,
aup.last_name,
aup.profileimage
from
(
select distinct
case when userid = $userid then friendid else userid end as id,
opid
from requestfriend
where $userid in (userid, friendid) and status = '2'
) as friend
inner join useractivitylog as ua on ua.userid = friend.id
inner join auth_user_profiles as aup on aup.user_id = friend.id;

This should work as you explained you need to get the activities of users who are friends with you, you first need to join useractivitylog table to requestfriend where friendid is in useractivitylog i.e ON(rf.friendid =ua.userid) then you need to join auth_user_profiles table where userid from useractivitylog table is equal,i.e ON(ua.userid=aup.user_id) and then use you where filter on rf.userid is equal to the provided user id ,i didn't get the point of using OR rf.friendid = $userid comparison when you asked for the friends activity then why comparing friend's id to the given user id
SELECT
ua.*,
rf.opid,
aup.user_id AS aup_user_id,
aup.first_name,
aup.last_name,
aup.profileimage
FROM
useractivitylog AS ua
INNER JOIN requestfriend AS rf ON(rf.friendid =ua.userid)
INNER JOIN auth_user_profiles AS aup ON(ua.userid=aup.user_id)
WHERE
rf.userid = $userid
AND rf.status = '2'
Using a sub select
SELECT
ua.*,
aup.user_id AS aup_user_id,
aup.first_name,
aup.last_name,
aup.profileimage
FROM
useractivitylog AS ua
INNER JOIN auth_user_profiles AS aup ON(ua.userid=aup.user_id)
WHERE
ua.userid IN (
SELECT friendid FROM requestfriend WHERE userid =$userid AND `status` = '2'
)

Try as below query
select * from useractivitylog a,requestfriend b,auth_user_profiles c
WHERE a.userid = b.userid and b.userid = c.userid;

You could go from the other side to your data...
Start with selecting all your friends and if you have them, get their data:
SELECT
ua.*,
rf.opid,
aup.user_id,
aup.first_name,
aup.last_name,
aup.profileimage
FROM
requestfriend AS rf
JOIN
useractivitylog AS ua ON (ua.userid = rf.friendid)
JOIN
auth_user_profiles AS uap ON (uap.userid = rf.friendid)
WHERE rf.userid = $userid AND rf.status = '2'
The rest with the vice-versa connection in your requestfriend table should be no problem.
Since the friendrequests should be not as much as the activities, this might lead to better performance in case you have loads of data...

You need to add a field to JOIN your first table on:
SELECT ua.*, rf.opid, aup.user_id, aup.first_name, aup.last_name, aup.profileimage
FROM useractivitylog as ua
INNER JOIN requestfriend as rf on fieldname = fieldname
INNER JOIN auth_user_profiles as aup on aup.user_id = IF (rf.userid='$userid',rf.friendid,rf.userid)
WHERE (rf.userid=$userid or rf.friendid=$userid)
AND rf.status='2'
AND ua.userid!=$userid

Related

How do I get friend list from Friends table with counts of friends of my friends

How do I get friend list from Friends table with counts of friends of my friends (Count not of my friends)
Friends table"
tbl_users_friends
Field 1: id
Field 2: user_id
Field 3: friend_user_id
and I need the out put as:
A has following friedns:
x (10)
y (2)
z (0)
Above is the list of my friends and in parenthesis contains their friends count.
Thanks
select user_id, count(*) cnt
from Friends
where user_id in
(select friend_user_id
from Friends
where user_id = user_id_of_A)
group by user_id
Try something like this:
select u.user_id, u.name, count(uf1.id) as num_friends
from tbl_users_friends uf
inner join tbl_users u on u.user_id = uf.friend_user_id
left join tbl_users_friends uf1 on uf1.user_id = uf.friend_user_id
where uf.user_id = 1
group by u.user_id, u.name
http://sqlfiddle.com/#!9/10033/1
You need to ajust the users table and column names.
Another solution with a subselect but without group by:
select u.user_id, u.name, (
select count(*)
from tbl_users_friends uf1
where uf1.user_id = uf.friend_user_id
) as num_friends
from tbl_users_friends uf
inner join tbl_users u on u.user_id = uf.friend_user_id
where uf.user_id = 1

Resolve data for 2 tables

Let's say, I have 3 tables. "users", "topics" and "replies.
The "topics" and "replies" table do have a column "user_id" which references to "id" on the "users" table. The "replies" table also have a column "topic_id" which references "id" on "topics". Also imagine that each topic has 1 reply.
Now, I want to fetch all topics and resolve the username for both tables, so the output should include a "topic_username" and a "reply_username".
I know how to select the username for the topic, but how can I do that for both the topics and replies table?
Thanks
Updated code:
SELECT
t.*,
t_users.username as topic_user,
last_reply.user_id as last_reply_user_id,
r_users.username as last_reply_username,
last_reply.replies_count,
ORDER BY IFNULL(last_reply.created_at,t.created_at DESC
FROM
topics as t
left join users as t_users on t_users.id = t.user_id
left join ( select r.*,count(r.id) as replies_count from (select * from replies order by id desc) as r group by r.topic_id ) as last_reply on last_reply.topic_id = t.id
left join users as r_users on r_users.id = last_reply.user_id
Try this
SELECT
t.*,
t_users.name as topic_user,
r_users.name as reply_user
FROM
topics as t
left join replies as r on r.topic_id=t.id
left join users as t_users on t_users.id = t.user_id
left join users as r_users on r_users.id = r.user_id
this would work well if there is 1:1 topic and reply, if you have 1 to many replies then you are better off group by topic id and get the usernames by group concat
Version 2 (to get reply count and last reply user)
SELECT
t.*,
t_users.name as topic_user,
last_reply.user_id as last_reply_user_id,
r_users.name as last_reply_username,
last_reply.replies_count,
IFNULL(last_reply.created_at,t.created_at) as last_update
FROM
topics as t
left join users as t_users on t_users.id = t.user_id
left join ( select r.*,count(r.id) as replies_count from (select * from replies order by id desc) as r group by r.topic_id ) as last_reply on last_reply.topic_id = t.id
left join users as r_users on r_users.id = last_reply.user_id
ORDER BY IFNULL(last_reply.created_at,t.created_at) DESC
You wanna do this in a single query? You can do it like this but I believe a separate query for fetching replies and topics might be better (fetch replies first, get the unique topic IDs and then fetch topics in a separate query)
SELECT r.id, r.topic_id, ru.username AS reply_username, tu.username AS topic_username
FROM replies AS r
INNER JOIN topics AS t ON (t.id = r.topic_id)
INNER JOIN users AS ru ON (r.user_id = u.id)
INNER JOIN users AS tu ON (t.user_id = u.id)

Fetching user from friends list and follow list

I am working on social networking site.
I've three tables one is user table which is used to store user details, another table is follow table which is used for followers following list.
In this table I am storing user_id and follower_id.
Third table is user_friends in this I'm storing user_id and friend_userid.
I want to search the user from my friends list and follow list. For this i've written query like this:-
select f.follower_id,uf.friend_userid,u.user_id,u.first_name,u.last_name from tbl_user u
LEFT JOIN tbl_userfriends uf ON uf.friend_userid = u.user_id
LEFT JOIN tbl_follow f ON f.follower_id = u.user_id
where uf.friend_userid != '11'
AND u.first_name LIKE '%a%'
This query returning users only who are friends it is not returning the follow users.
Any help will be appreciated. Thanks in Advance.
You're joining tbl_follow on the Follower ID being equal to the User ID. I suspect that's probably not right.
If you don't already have one you'll need a user id key in the follower table to join on, then you can change your join to;
LEFT JOIN tbl_follow f ON f.userid = u.user_id
i've done this by using following query:-
select u.user_id,u.first_name,u.last_name from tbl_user u LEFT JOIN tbl_userfriends uf ON uf.friend_userid = u.user_id LEFT JOIN tbl_follow f1 ON f1.follower_id = u.user_id LEFT JOIN tbl_follow f2 ON f2.user_id = u.user_id where (uf.user_id = '11' OR f1.user_id = '11' OR f2.follower_id = '11') AND (u.first_name LIKE '%s%' OR u.last_name LIKE '%s%') AND u.status = '0' group by u.first_name
This query returning me all the users who are my followers, friends and to whom i am following.

Select a row from two tables depend on primary key(Mysql)?

I have two table users and album. In users table there is user_id primary key .In other table albums there are multiple rows with that user_id because every time when a user upload a new album it uploads with user_id as foreign key. I want to select only once the user_id with other table(album) ignore other result set.
How can I achieve this?
SELECT a.*, b.*
FROM users a
INNER JOIN album b
ON a.user_ID = b.user_ID
INNER JOIN
(
SELECT user_ID, MAX(photo_id) max_rec
FROM album
GROUP BY user_ID
) c ON b.user_ID = c.user_ID AND
b.photo_id = c.max_rec
SELECT album.* FROM album LEFT JOIN users ON user.id = album.id WHERE user.id = SOMEIDHERE
I believe this will work, your not giving me a whole lot of info to work with.
SELECT *
FROM ( SELECT u.*, a.*
FROM users AS u
INNER JOIN album AS a
ON u.user_ID = a.user_ID
ORDER BY a.created DESC) AS h
GROUP BY user_ID
ORDER BY b.created DESC -> ORDER BY whatever row you wish for. In this case the newest one is chosen.

php mysql join exists

I have an application, very basic description:
Users login -> they post "activities" (like snowboarding)
Users have friends
Users can bind multiple friends to activities
Users can "like" activities created by friends
What I need is a query to check if the user is allowed to "like" an activity by one of their friends. They are only allowed when one of the users friends was bound to the target activity.
users: id, name
usersFriends: id, uid, friendUid
activities: id, description
activitiesUsers: id, activityId, uid
activitiesLikes: id, activityId, uid
I hope someone can help me with this query, and if possible to return true or false. I hope my question is clear and thanks for your time :)
This should produce a list of activities.id for all of the user's friends.
SELECT
activities.id AS canLikeId
FROM
users u
JOIN usersFriends uf ON u.id = uf.uid
JOIN activitiesUsers au ON uf.friendId = au.uid
JOIN activities a ON a.id = au.activityId
Wrapped in an EXISTS, it looks like:
SELECT activities.id FROM activities aCanLike
WHERE EXISTS (
SELECT
a.id AS canLikeId
FROM
users u
JOIN usersFriends uf ON u.id = uf.uid
JOIN activitiesUsers au ON uf.friendId = au.uid
JOIN activities a ON a.id = au.activityId
WHERE a.id = aCanLike.id
)
Or something with an IN() clause that attempts to get everything from activities owned by any of the user's friends.
SELECT
activities.*
FROM activities JOIN activitiesUsers ON activities.id = activitiesUsers.activityId
WHERE activitiesUsers.uid IN (
SELECT friendUid FROM usersFriends WHERE uid = $userid
)
Assuming you know the user's id and activity id at the time of the query, you could do something like:
SELECT COUNT(*) FROM activitiesUsers WHERE activityId = 'xx' AND uid IN (SELECT friendUid FROM usersFriends WHERE uid = 'xx')
Should return 0 if none of their friends are bound to the activity or a positive number if they have friends bound to that activity ...
This should do it:
select
count(*) as CanLike -- 0 if false, >= 1 if true
from
usersFriends uf
join
activitiesUsers au
on
uf.friendUid = au.uid
where
au.id = $activityId
and
uf.uid = $userId
SELECT COUNT(*) AS allowed
FROM userFriends
JOIN activitiesUsers ON (userFriends.uid = activitiesUsers.uid
AND activitiesUsers.activityId = $activity_id)
WHERE userFriends.uid = $user_id

Categories