PHP MySQL Search for users by mutual friends and country - php

I am developing a sort of social network of sorts. Today I started making a dynamic search bar with AJAX and php. In in I have a query that searches for users in a "users" table. I would like to order my search results by relevance, if you know what I mean. Like for instance if I have user with id 3, searching for John, I would like to order the results by the number of mutual friends, and possibly where the person is living.
My tables look like this
Users
id| name | country
Friends
id|user_id|friend_id
the queries I have for the moment are
SELECT * FROM users WHERE name LIKE $keyword
for user searching
and
SELECT COUNT(*) as mutual from users where id in
(select friend_id from friends where user_id = 3 and friend_id in
(select friend_id from friends where user_id = 7)
This for instance will return the number of mutual friends between user 3 and user 7.
How can I combine the two, in order to give more relevant search results?
Thank you in advance!

Like for instance if I have user with id 3, searching for John, I
would like to order the results by the number of mutual friends
Find friends of my friends whos name contains 'john' order by number of mutual friends:
select u.*, count(f1.user_id) as num_mutual_friends
from friends f1 -- my friend
join friends f2 on f2.user_id = f1.friend_id -- friend of my friend
join users u on u.id = f2.friend_id
where f1.user_id = 3
and u.name like '%john%'
and u.id <> 3
group by u.id
order by num_mutual_friends desc;
Show users from US first:
order by (u.country = 'us') desc, num_mutual_friends desc;
http://sqlfiddle.com/#!9/728c8a/3

Related

Mysql display random 4 users with more than 5 articles

I have users table and also articles tables. Article table contains articles submitted by users. I am working on a sql query to display random 4 users with more than 5 articles. user_id is stored in articles table. I have searched around in stackoverflow and google even though there are some similar questions, i couldn't find anything specific to mine.
Can anyone let me know if this question has been answered before and give me a link if yes otherwise I have the following query:
SELECT *
FROM users WHERE type = 3
INNER JOIN articles ON
users.user_id = articles.user_id HAVING COUNT(user_id) > 5
This doesn't seem to work. I will appreciate any help to improve this query.
Database table is as follows:
USERS:
user_id
username
email
type
ARTICLES:
id
user_id
title
For example, total user count is 100. User with user_id 49 has 10 articles, and another user with user_id 50 has 20 articles and the rest of the users have less than 5 articles. So the query should return only the user 49 and 50.
Hope this makes sense.
regards
I've mocked up some table data to test my query. WHERE clauses must be positioned after JOINs. You are also a little ambiguous about the comparison of COUNT AND 5 -- if you want more than 5 then >5, if you want 5 or more then >=5.
SQL: (SQLFiddle Demo)
SELECT a.user_id,a.username,COUNT(b.user_id)
FROM users a
INNER JOIN articles b ON a.user_id=b.user_id
WHERE a.type=3
GROUP BY a.user_id
HAVING COUNT(b.user_id)>5
ORDER BY RAND()
LIMIT 4
You have where join and having in wrong position, you missed group by for a correct functioning of having
and you need an order by rand and limit 4
SELECT u.user_id
FROM users u
INNER JOIN articles a ON u.user_id = a.user_id
WHERE a.type = 3
group by u.user_id
HAVING COUNT(a.user_id)>= 5
order by rand() limit 4

php friend system, display friends of my friends

I have a table named friends, keeps my friends in a php friend system. The table is as follows:
friend_id | user_one | user_two
My script is the following for displaying my friends.
$check_friend_query = mysql_query(" SELECT friends_id from friends WHERE (user_one='$session_user_id' AND user_two ='$user_id') OR (user_one='$user_id' AND user_two='$session_user_id') ");
if( mysql_num_rows($check_friend_query) == 1 ){
echo" 1st degree friend";
}
All I want is to display 2nd degree friends. My 2nd degree friends are the friends of my friends. Any idea how to do this?
You can run an original query to grab all of your friends (like you have), then another to find their friends using their user ID as the variable to look for.
mysql_query("SELECT friends_id from friends WHERE user_one='$user_id'");
Something like this would check friends_id for all friends where the name is the user_id of the person.
Although the variables are a bit difficult to figure out, since I don't know the script.
Join the friends against itself:
SELECT degree2.*
FROM friends
LEFT JOIN friends AS degree2 ON friends.user_two = degree2.user_one
WHERE friends.user_one = 'original friend';
For further degrees, you'd just add another join level, e.g.
LEFT JOIN friends AS degree3 ON degree2.user_two = degree3.user_one
LEFT JOIN friends AS degree4 on degree3.user_two = degree4.user_ond
etc...

Inner, outer or full join on three tables in MySQL database on linux with apache

I want to have some help creating my query to get information from three different tables sharing information in common.
My first table is:
auctions
id title description user_id(who posted it)
My second table is:
bids
id user_id bid auction_id owner_id
My third table is:
users
id username X XX XXX XXXX
...and my SQL is as follows however it's not returning any results:
SELECT auction_bids.user_id AS applicant, auction_bids.*, auctions.title FROM auction_bids, auctions
WHERE auctions.user_id=".$_SESSION['userid']."
INNER JOIN users ON auction_bids.user_id = users.id
WHERE auction_bids.owner_id = ".$_SESSION['userid']."
What I need is to capture the auction's title, username who bidded on the auction and the bid. the auction has to have a bid and posted by the user who owns the $_SESSION['userid'].
Any help is appreciated.
You have two different 'where' statements, which may just need combining;
SELECT auction_bids.user_id AS applicant, auction_bids.*, auctions.title FROM auction_bids, auctions
INNER JOIN users ON auction_bids.user_id = users.id
WHERE auction_bids.owner_id = ".$_SESSION['userid']." AND auctions.user_id=".$_SESSION['userid']."
However, I'm not sure this is really what you want, as it will return only records where the specific user both 'owns' the item AND has bidded on it (both based on the userid session), rather than displaying all records from different people who have bidded on an item 'owned' by the user.
Something like: ?
SELECT auction_bids.user_id AS applicant, auction_bids.*, auctions.title FROM auction_bids, auctions
INNER JOIN users ON auction_bids.user_id = users.id,
WHERE auction.owner_id = ".$_SESSION['userid']."
Hope this points you in the right direction!
you have 2 where clauses, that is incorrect. I have revised your query based on your requirements.
SELECT auction_bids.user_id AS applicant, auction_bids.*, auctions.title
FROM auction_bids, auctions
INNER JOIN users ON auction_bids.owner_id = users.id
WHERE auction_bids.owner_id = ".$_SESSION['userid']."
AND auctions.user_id=auctions_bids.owner_id

Get mutual friends from Facebook friends (MySQL table)

I'm trying to get mutual friends between 2 people.
I've saved the persons friends in a table called "friends" with the following fields:
id | facebook_id | name | uid | timestamp
id = unique id for the record
facebook_id = the friends facebook id
name = the friends name
uid = the users uid on my site, which is a friend to the person saved in the table
timestamp = don't need to explain :-)
Hope it make sense, have tried various ways to get the friends, but without luck
I dont know if using subqueries would be faster or mySQL already optimizes it.
Solution with subqueries:
SELECT f1.id, f1.name
FROM (SELECT id, name FROM friends WHERE uid=1) f1
JOIN (SELECT id, name FROM friends WHERE uid=2) f2
ON f1.id=f2.id;
It would be nice if MySQL has an INTERSECT operator, but...
You can grab all the friends of one person:
SELECT id, name
FROM friends
WHERE uid = 1
You could then JOIN this list back to the friends table, looking for the same friend for the other user:
SELECT f1.id, f1.name
FROM friends f1
JOIN friends f2 on f1.id = f2.id
WHERE f1.uid = 1
and f2.uid = 2
It's pseudo-code, but it should be close.

Friend of a friend in PHP/MySQL?

I have a social network similar to myspace/facebook. In my code you are either a person's friend or not a friend, so I show all actions from people you are friends with (in this post I will refer to actions as bulletin posts alone to make it easier to visualize.
So you every time a person post a bulletin it will show up to any person who is there friend.
In mysql you would get a persons friend list by doing something like this,
SELECT user_id FROM friends WHERE friend_id = 1 (user ID)
I want to know how a site like facebook and some others would show all bulletin post from your friends and from your friends' friends?
If anyone has an idea please show some code like what kind of mysql query?
The answer is that they aren't doing selects on a friend table, they are most likely using a de-normalized news-event table. We implemented a news-feed similar to Facebooks on DoInk.com, here's how we did it:
There is the notion of a "NewsEvent" it has a type, an initiator (a user id) and a target user (also a user id). (You can also have additional column(s) for other properties relevant to the event, or join them in)
When a user posts something on another users wall we generate an event like this:
INSERT INTO events VALUES (wall_post_event, user1, user1)
When viewing user1's profile, you'd select for all events where user1 is either the initiator or the target. That is how you display the profile feed. (You can get fancy and filter out events depending on your privacy model. You may consider doing this in memory for performance reasons)
Example:
SELECT * FROM events WHERE initiator = user1 or target = user1 //to see their profile feed
SELECT * FROM events WHERE initiator IN (your set of friend ids) //to see your newsfeed
When you want to see the newsfeed for all events relative to your friends you might do a query selecting for all events where the initiator is in your set of friends.
Avoid implementations with sub-selects, depending on the complexity, they will not scale.
you do a subquery:
SELECT DISTINCT user_id FROM friends WHERE friend_id IN
(SELECT user_id FROM friends WHERE friend_id = 1)
Test both of these for performance:
SELECT DISTINCT user_id
FROM friends f1
JOIN friends f2 ON f1.friend_id = f2.user_id
WHERE f2.friend_id = 1
and
SELECT DISTINCT user_id
FROM friends
WHERE friend_id IN (SELECT user_id FROM friends WHERE friend_id = 1)
Often they're the same but sometimes they're not.
Make sure friend_id and user_id are indexed.
The simple approach would be to do some kind of simple nested clause. So say you have a table with posts and the posters id, and a friends table, the first layer would be
SELECT post FROM posts JOIN friends
on post.userid = friends.friend_id
WHERE friend.id = 1 (user ID)
then to get a friends of friends
SELECT post FROM posts JOIN
(SELECT DISTINCT friends_2.friend_id FROM friends AS friends_1
JOIN friends as friends_2
on friends_1.friend_id = friends_2.id where friends_1.id = 1)
AS friends
wHERE post.userid = friends.friend_id AND mainid = 1 (user ID)
You can repeat this nesting each time you want to add another layer of friend abstraction. The problem with this approach is that it would take a very long time to execute. For every time you add a layer of friend abstraction you are increasing the complexity by a power of n (where n is the number of rows in your table).
It is more likely that they are saving the viewable friends in a table somewhere, so lets make a new tabled called friends_web
user_id, friend_id, level
when a user friends someone, it adds that new friend into friends_web at a level of 0(since that friend is no people away) then adds that friends friends at a level of 1 (since its 1 friend away). In order to keep the table integrity you would also want to add the inverted record. To clarify if A adds B as a friend and C is a friend of B, the following two records would get added to our new table
A, C, 1
C, A, 1
since now A can see C and C can see A.
now when we want a query we just do
SELECT post FROM posts
JOIN friends_web ON post.user_id = friends_web.friend_id
WHERE friends_web.user_id = user_id AND friends_web.level < 2 (or however deep you want to look)
by doing that you minimized your query complexity when doing post lookups while being able to look more then 1 layer deep into a friend web.
Sorry for the long winded response.
This should pull out all the user's friend's posts.
SELECT * FROM posts WHERE uid IN (SELECT friend_uid FROM friends WHERE uid=1) ORDER BY post_id DESC
This should pull out all posts that are your friend's friend's.
SELECT * FROM posts WHERE uid IN (SELECT friend_uid FROM friends WHERE uid IN (SELECT friend_uid FROM friends WHERE uid=1)) ORDER BY post_id DESC

Categories