I am trying to make an SQL query on postgresql database that should give me posts feed of my posts and posts of users that I follow and my friends ( which is mutual follow ) I have this table structure
users table
id username
1 me
2 user2
3 user3
4 user4
relationships table
id follower_id following_id
1 1 2 // me following user2
2 2 1 // user2 also following me so we are friends
3 3 1
posts table
id user_id post visibility
1 2 post1 friends
2 2 post2 public
3 2 post3 public
4 1 post4 public
5 3 post5 public
select p.*
from posts p
where (
visibility = 'friends' and
user_id in (select following_id from relationships r1 where r1.follower_id = 1) and
user_id in (select follower_id from relationships r2 where r2.following_id = 1)
) or (
visibility = 'public' and
user_id in (select following_id from relationships r3 where follower_id = 1)
)
and this is the query I made which is giving a result but for me it is not an efficient query I need a better query to get the result as
user id 1's feed should be
id user_id post visibility
1 2 post1 friends
2 2 post2 public
3 2 post3 public
4 1 post4 public
Look next query:
select p.*
from posts p
join (
-- get followers and friends
select distinct relationships.*, coalesce(friends.follower_id, 0) as friend_id
from relationships
-- join self for check is follower friend
left join relationships friends on
relationships.following_id = friends.follower_id and
relationships.follower_id = friends.following_id
where relationships.follower_id = 1
) followers on (
visibility = 'friends' and followers.friend_id = p.user_id or
visibility = 'public' and followers.following_id = p.user_id
);
Try this query on SQLize.online
Related
I have searched for other questions and I was able to solve part of what I wanted but I couldn't get any further from that.
I have a table with two columns(user, friend) in Friends table.
Each user and his/her friend is specified in the table as bellow.
User | Friend
1 2
1 6
2 1
2 3
2 6
Note: For every (User, friend) pair there is a row (Friend, User)
Eg: 1,2 has 2,1 because User 2 has friend 1
So far, I have arrived at the below query which gives the count of mutual friends for the pair we specify:
select DISTINCT f1.user1 'User', f2.user1 'Friend', COUNT(DISTINCT f1.user2) 'Mutual friends'
from Friends p
inner join Friends f1 on f1.user2 = p.user1
inner join Friends f2 on f2.user2 = p.user1
where f1.user1 = 2 and f2.user1 = 3 and f1.user2 = f2.user2
group by f1.user1, f2.user1;
The output that I have now:
User |Friend |Mutual Friends
1 2 1
I want to find the count of mutual friends of each of pairs throughout the table:
User | Friend | Mutual Friends
1 2 1
1 6 0
2 1 1
2 3 0
2 6 0
How do I find the number of mutual friends for all user,friend pairs?
You can use a self-join:
select f1.user as user1, f2.user as user2, count(*) as num_in_common
from friends f1 join
friends f2
on f1.friend = f2.friend
group by f1.user, f2.user;
You can add a where clause if you want this information for a particular pair of users.
Here is my table structure.(fun_friends)
id user_id,friend_id,status,createdat,updatedat
1 1 2 1 123456 125461
2 1 3 1 454545 448788
3 2 4 1 565659 898889
4 1 5 1 877878 878788
Here is the table structure of user_uploads
id user_id parent_id category_id title slug tags description video_type source video_link video_thumb
1 2 1 2 fun fun ['4','5'] coolvid 1 ytu link thumb
I need to show the latest upload of my friends
Can you tell me how can i join this tables together? i tried with
SELECT * FROM fun_friends WHERE (user_id= '".$_SESSION['user_row_id']."' AND `status` =1) OR (friend_id= '".$_SESSION['user_row_id']."' AND `status` =1)
and it is showing all friends of logged-in user
You can just join both table using user_id field. sample query bellow will return one record with latest user_uploads.id.
select *
from fun_friends a
inner join user_uploads b on a.user_id = b.user id
order by b.id desc limit 0,1
how about using UNION to get the friends user and wrapping it inside a subquery which later join on the other tabel,
SELECT usr.*
FROM user_uploads usr
INNER JOIN
(
SELECT user_ID AS ID
FROM Fun_Friends
WHERE friend_ID = 'ID_HERE'
UNION
SELECT friend_ID As ID
FROM Fun_Friends
WHERE ser_ID = 'ID_HERE'
) idList ON usr.user_ID = idList.ID
I have a MySQL query that I used to use to return mutual friends between two users, but now that I am recoding my website, I am trying to simplify this code, or at least make it better.
So here's my code below to check mutual friends:
SELECT a.friendID
FROM
(SELECT CASE WHEN userID = $id
THEN userID2
ELSE userID
END AS friendID
FROM friends
WHERE (userID = $id OR userID2 = $id)
AND state='1'
) a
JOIN
(SELECT CASE WHEN userID = $session
THEN userID2
ELSE userID
END AS friendID
FROM friends
WHERE (userID = $session OR userID2 = $session)
AND state='1'
) b
ON b.friendID = a.friendID
My table is set up like this:
userID -- userID2 -- state
1 ------- 2 ------- 1
2 ------- 3 ------- 1
1 ------- 3 ------- 0
(sorry, I don't know how to do the pretty database structure design, so if someone could edit that for me...)
but for the above, when user 1 is on user 3's profile, since user 1 and user 2 are friends, and user 2 and user 3 are friends, but user 1 and user 3 are not, it should return user 2 as a mutual friend. (state 1 means friendship accepted, state 0 means friendship pending, so only if state is 1 should it be counted as a friend)
Also note that userID and userID2 can be in any order, it depends on who requests who as a friend, so like the above query does, I need to also have the "friendID" returned, as the above query does right.
SELECT t.f FROM friends JOIN (
SELECT IF(userID = $id, userID2, userID) f
FROM friends
WHERE state AND $id IN (userID, userID2)
) t ON t.f IN (userID, userID2)
WHERE state AND $session IN (userID, userID2)
See it on sqlfiddle.
Not necessarily the fastest but simple to read:
Create View ActiveFriends As
Select
UserId, UserID2
From
friends
Where
State = '1'
Union All
Select
UserId2, UserID
From
friends
Where
State = '1'
Select
f1.userID2 as MutualFriendId
From
ActiveFriends f1
Inner Join
ActiveFriends f2
On f1.UserID2 = f2.UserID
Where
f1.UserID = $session And
f2.UserID2 = $id
http://sqlfiddle.com/#!2/5748f/1/0
You could do :
SELECT userID2
FROM friends_table
WHERE userID IN ( $id, $session )
AND state = 1
GROUP BY userID2
HAVING COUNT(userID2) >= 2
friends_table :
user_id | friend_id | state
-----------------------------
1 | 7 | 1
2 | 3 | 0
7 | 1 | 1
User 1 and 7 are friends, user 2 wants to be friends with user 3, but user 3 hasn't responded yet.
at the first glance I would say that using intersect is a good solution
so this query should do the trick for you
SELECT userID2
FROM friends
WHERE userID = $fromID
INTERSECT
SELECT userID2
FROM friends
WHERE userID = $theOtherID
EDIT:
another less clear solution would be
SELECT userID2
FROM friends INNER JOIN friends f2
USING (userID2)
WHERE friends.UserID = $fromID AND f2.userID = $theOtherID
I have looked through some of the other posts on this site and am not seeing exactly what im looking for so here goes.
Lets say i have 2 tables
juser
-----------------------------
userID firstName lastName
-----------------------------
1 billy bob
2 jezze belle
3 bobbie sue
and:
juserrel
---------------------------------------------
id userID relUserID state
---------------------------------------------
1 1 2 approved
2 2 1 retired
3 2 1 approved
4 3 2 approved
What i am trying to do is get a result set that shows each user info about each user in the juser table and adds a column called connections to the result set which shows how many "active" connections a particular user has to another user.
the result i expect based on the tables above is
resultSet
-----------------------------------------------
userID firstName lastName connections
-----------------------------------------------
1 billy bob 2
2 jezze belle 3
3 bobbie sue 1
The query I tried is as follows
select userID, firstName, lastName , coalesce(x.cnt,0) as connections
from juser
left outer join (select count(*) cnt from juserrel where juserrel.userID =
userID or juserrel.relatedUserID = userID and juserrel.state = 'approved')
x on userID = userID
The result set i get looks like this:
resultSet
-----------------------------------------------
userID firstName lastName connections
-----------------------------------------------
1 billy bob 4
2 jezze belle 4
3 bobbie sue 4
Help Please ;)
Try:
select u.userID, u.firstName, u.lastName,
count(case when ur.state = 'approved' then 1 end)
from juser u
inner join juserrel ur on u.userID = ur.userID or u.userID = ur.relUserID
group by u.userID, u.firstName, u.lastName
SQL Fiddle Example
I have a database with users and games. 1 game can have multiple users so I made a linking table called users_games. The crux is that a game can always only have 2 players since it is a board game. I know which player I am, i have my user_id and my email, but I would like to gain a result that gives me a list of all games I am in WITH the user_id and email of the other fellow. So a query that looks to all games I am in and give the other row, with the name of the player.
My tables:
games
id (int)
board (varchar) representation of the board
users
id (int)
email (varchar)
password (varchar MD5)
users_games
id (int)
user_id (int)
game_id (int)
For clarification this query
SELECT *
FROM `tic_users_games` AS ug
LEFT JOIN tic_users AS u
ON ug.user_id = u.id
RIGHT JOIN tic_games AS g
ON ug.game_id = g.id
And result
id user_id game_id id email password id board created updated
1 1 1 1 ME#gmail.com d56b699830e77ba53855679cb1d252da 1 0|0|0|0|0|0|0|0|0 2012-04-02 16:56:06 2012-04-02 16:56:06
2 2 1 2 FOE1#gmail.com d56b699830e77ba53855679cb1d252da 1 0|0|0|0|0|0|0|0|0 2012-04-02 16:56:06 2012-04-02 16:56:06
3 3 2 2 FOE2#gmail.com d56b699830e77ba53855679cb1d252da 2 0|0|0|0|0|0|0|0|0 2012-04-02 16:56:06 2012-04-02 16:56:06
4 1 2 1 ME#gmail.com d56b699830e77ba53855679cb1d252da 2 0|0|0|0|0|0|0|0|0 2012-04-02 16:56:06 2012-04-02 16:56:06
See: In the above case I just want 2 rows: game_id 1 and 2, with FOE1#... and FOE2#...
Thanks
This should do it for you. The syntax might not be exact for mysql but you should get there. Basically get all users that have games in the user_games table with the same game_ID as the games I am in:
SELECT
User_Games.Game_ID,
Users.ID,
Users.Email
FROM
Users
LEFT JOIN User_Games ON Users.ID = User_Games.User_Id
WHERE
Users.User_ID <> #yourUserID
AND EXISTS
(SELECT
NULL
FROM
User_Games AS MyUserGames
WHERE
User_Games.Game_ID = MyUserGames.Game_ID
AND MyUserGames.User_ID = #yourUserID)
Try this (where #userid represents the user you are searching games for, in this case, 1):
select *
from tic_users_games ug1
left join tic_users_games ug2 on ug1.game_id = ug2.game_id
left join tic_users u on ug2.user_id = u.id
right join tic_games g on ug2.game_id = g.id
where ug1.user_id = #userid
and ug2.user_id <> #userid
Demo: http://www.sqlfiddle.com/#!2/7b0f6/2