I'm making a social networking site and I have two types of statuses. Friends and Public. Users can upload to either. The relevant tables for this question are members, friends, and status. Relevant field for members is Handle. Relevant fields for friends are Friend and Username. Relevant fields for status is Handle and type(with values friends or public).
I managed to call the statuses I needed for only friends, but my question is how do I get it to show friends as well as the user's statuses
Here's the code that shows all statuses from a user's friends.
$shawing = "SELECT *
FROM status
JOIN friends
ON status.Handle = friends.Friend where friends.Username='$members[Handle]' and status.Type='friends' ORDER by status.Id DESC" or print mysql_error();
$members[Handle] calls from an include that identifies the user who is logged in.
I know it's probably simple but how do I correct it to show both the friends AND user statuses?
UNION them together (merge two queries)
$shawing = "
SELECT 1 IsUser, '$members[Handle]' Friend, status.*
FROM status
where status.Handle='$members[Handle]'
and status.Type='friends'
UNION ALL
SELECT 2 IsUser, friends.Friend, status.*
FROM status
JOIN friends ON status.Handle = friends.Friend
where friends.Username='$members[Handle]'
and status.Type='friends'
ORDER by IsUser, status.Id DESC" or print mysql_error();
Change it to a 'right join'. You're blocking on values for 'status' that don't have related entries in 'friends'. You could probably lose lots of the 'where' clause too.
Related
I`m working on a small website where people can follow each other. There are newsfeed on the site where users can see updates from other users that they follow. The problem is that I can see only posts from other users and not my posts. I want the current user to be able to see his posts too Ordered within the other users posts. Something like Facebook Wall.
I have tried tons of differend queries and php, but I get only other users post or when i manage to pull out my posts too there are dublicate post for every user that follows me.
I have 3 tables 'members', 'Post' and 'follow'. The members table hold UserID, Name and Last Name. Post table holds the UserID(FromID in the table) Indexed to members UserID and the post from the user. In the follow table there are 3 columns FollowID, Followed and Follower both Followed and Follower are index to members UserID.
At the moment I use that query:
$query= "SELECT Post.*, members.*, follow.* FROM Post
INNER JOIN members ON Post.FromID=members.UserID
LEFT JOIN follow ON members.UserID=follow.Followed
WHERE Post.FromID='$user' OR follow.FollowerID='$user'
ORDER BY Post.date DESC, Post.time DESC";
$user is the UserID of the current logged in user.
That query returns all the posts that I want but the problem is that my post are show /n times for each user that follows me.
I really would appreciate the kindness to the one that give me some directions what i do wrong. Thank you
The problem is with your $user. Currently what is happening is that you have an OR condition in where clause. And you are trying to pull either your data or ur followers data.
My solution for you would be to remove $user from the query you have. So you will have list of followers data only. Have a different query for your posts and then while displaying sort them by datetime Timestamp so you have your posts with other followers too.
To have your posts and folloeers posts in one query.
Use union. Like :
(Query of your posts ORDER BY date)
UNION
(Query of followers posts ORDER BY date);
Also check UNION usage in w3schools.
Hope this helps
I think this query might be easier to understand:
$query = "SELECT * FROM Post,members,follow
WHERE
Post.FromID=members.UserID
AND
members.UserID=follow.Followed
AND ( Post.FromID='$user' OR follow.FollowerID='$user')
ORDER BY Post.date DESC, Post.time DESC";
Consider this mysql tables structure (useful to store private/group chat messages):
USERS
user_id
username
password
GROUPS (= DISCUSSIONS / TOPICS)
group_id
name
GROUPS_MEMBERS (= MEMBERS OF A SPECIFIC DISCUSSION / TOPIC)
group_id
user_id
MESSAGES
message_id
timestamp
from_user_id
destination_type (enum - group, user)
destination_id
Can you please help me with the query to retrieve the list of the 5 more recent dicussions (either private or group) in which a specific user has been a active?
Important:
I don't have actual code since I'm just deciding how to structure the database tables. The table structure presented above it's pretty self-explanatory (destination_id is a reference to group_id, and group members are all the users that will receive a message. Finally, all messages sent between the users of a specific group make a discussion or topic).
Here is what I want to do (it's very easy... don't over-think it... it's like any chat/messaging system like Facebook or Gmail etc).
When a user logs in and opens the chat he will of course see all the latest discussion which he is/has been a part of. In a chronological DESC order.
So I need to write the query to retrieve the latest 5 GROUP_IDs (= discussions) in chronological DESC order. But only the discussions which the logged-in user is a part of.(Of course I have the id of the logged-in user.. for example 16)
P.s. I didn't build this table structure myself but it seems logic; the only problem is the one presented above.
Here's my suggestion. You can get different records by using DISTINCT and get only five records by using LIMIT. You can replace logged_in_user_id with the login id.
SELECT DISTINCT GROUPS.group_id FROM USERS
JOIN GROUP_MEMBERS ON USERS.user_id = GROUP_MEMBERS.user_id
JOIN GROUPS ON GROUPS.group_id = GROUP_MEMBERS.group_id
JOIN MESSAGES ON destination_type = 'group' AND destination_id = GROUPS.group_id
WHERE USERS.user_id = logged_in_user_id
ORDER BY timestamp DESC
LIMIT 5;
#Igor Carmagna:
I have gone through your question and according to that i think you are required list the top 5 messages which have been left by the end users right ?. So for that please please follow below given steps.
1) First and for most thing you are required to do is that Join.
2) In this step you are required to use max() function which will give you list of the users on the base of messages received. Now, according to your question you are required to have only top 5 records so you are bound use (max-5) function this will given top 5 records
Hope this will make you day !!
Cheers :) :P
I have a big problem with MySQL. I want to write script like facebook newsfeed.
My query return me 27 the same records. I don't know why.
How it works?
Script displaying posts written by me, my friends or my profile.
My tables:
users:
id, firstname, lastname
friends:
friend1, friend2, status, date
wall:
update_id, author, to_profile, content, date, photos
My query:
SELECT wall.update_id, wall.author, wall.to_profile, wall.content, wall.date, wall.photos, users.*, friends.sender_id, friends.friend_id, friends.status
FROM
wall
INNER JOIN friends ON
wall.author = friends.sender1
AND friends.friend2 = '".$_SESSION['id']."'
AND friends.status = '1' OR wall.author = '".$_SESSION['id']."'
OR wall.to_profile = '".$_SESSION['id']."'
INNER JOIN users ON users.id = wall.author
ORDER BY wall.date DESC
I also want to display post written by pages which I liked.
I created tables:
pages:
page_id, page_name
page_likes:
page_id, user_id, date
and *pages_wall:**
like_id, page_id, user_id, date
How to connect this to my query? And (the most important) how to repair my query?
Thanks in advance,
Matthew
That's a lot of joining going on. Try using your JOINs just to connect the tables, and then use WHERE to cut down the results. Because as it stands, those ORs aren't working like you probably think they are, they need some () around them.
I think you need some structural changes to this database for it to work well in the future. I'd add an ID field to friends, even if just on the admin side, you're going to want to manage those records.
Also, you shouldn't be querying user.* in this query. It seems like you want to pull out every user setting... for every single wall post. This will get rid of "INNER JOIN users ON users.id = wall.author " at the end which will help. Get that information in it's on query prior to calling this wall display.
SELECT *
FROM users
WHERE users.id = wall.author
The website is intended for users to enable them joining the courses and posting their updates to these courses and also receiving the course updates made by others (imagen courses as Groups in Facebook but in my website users post updates ONLY through the courses)
When the user login to the website, he is suposed to see all the updates in the courses he already is joined in.
I have many tables in MySQL :
'updates' which have these attributes (id, account_id,course_id,datetime,content) noticing that course and account ID's are foreign keys..
'courses' which have these attributes (id,name,..)
'accounts' which have these attributes (id,full_name,...)
'accounts_courses_relationship' (account_id,course_id) , to map the relations between users and courses.
I have tried many times but the only thing I get is to show all the updates for all courses without excluding the updates from the courses that user isn't a member of, as follow:
$sql = "SELECT DISTINCT datetime, content
FROM updates
WHERE account_id != {$account_id}
ORDER BY datetime DESC
LIMIT 10";
So, How to exclude the updates from these courses?
Note: don't forget that all mappings between users and courses are registered in a table shown above..
Well i might be not seeing your problem it but how about
SELECT ... FROM updates where account_id = {$account_id}
Would't this select all updates for the current user and therefore all the updates the user is interested in?
something like this should work
select *
from updates u
join accounts_courses_relationship r on u.courseid = r.courseid
where r.account_id = {$account_id}
You have to inner join the updates and courses and accounts and accounts_courses tables.
select acr.accountid, acr.courseid, courses.name, accounts.fullname, updates.datetime, updates.content
from accounts_courses_relationship acr
inner join courses on acr.courseid=courses.courseid
inner join accounts on acr.accountid = accounts.accountid
inner join updates on updates.accountid= accounts.accountid and updates.courseid=courses.courseid
where accountid = {?}
order by updates.datetime desc
If you're interested in seeing updates to courses from other users (not you) and you're a registered user of those courses:
SELECT DISTINCT datetime, content
FROM updates
WHERE account_id != {$account_id}
and course_id in (select acr.course_id from accounts_courses_relationship acr where acr.account_id = updates.account_id)
ORDER BY datetime DESC
LIMIT 10
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