How does Twitter (or Facebook) do to retrieve a user feed?
Here is the database schema I am working on. I renamed everything to look like twitter hoping that the most of you would understand my question...
I only have two resources: users and tweets. So here are those two tables:
users:
- id
- username
tweets:
- id
- author_id
- content
Let's continue with a simple pivot table to associate tweets and users:
user_tweet:
- user_id
- tweet_id
- created_at
This pivot table is here mainly to store the retweets. But it also stores the original tweets for more convenience.
For example, let's take user 1 tweets 'something'. user 2 and user 3 retweet. The user_tweet table will have three rows.
And, let's see a last table that complicates everything: The Following System.
Every user can follow an other user. I named the table "followee_follower":
followee_follower:
- followee_id
- follower_id
The followee_id is the user.id of the person being followed
The follower_id is the user.id of the person that follows an other one
Now let's get to the SQL problem:
I'm user 1. I follow user 2, and user 3.
How can I retrieve the tweets and retweets from user 2 and user3 knowing that I want to retrieve them ordering them by the created_at field of the user_tweet table, and that I don't want to get two similar tweets.
Many thanks, any help is highly nice from you,
Have a good day/night.
EDIT: Here are some samples data from tables:
users table
tweets table
user_tweet table
followee_follower table
expected results
I'm not sure I completely understand your question (sample data would help), but I think you just need to use multiple joins:
select t.id, t.content, ut.created_at
from tweets t
inner join user_tweets ut on t.id = ut.tweet_id
inner join followee_follower ff on ut.user_id = ff.follower_id
where ff.followee_id = 1
order by ut.created_at
Perhaps if a user retweets, you'd want to do something like this instead to get the first tweet (assuming the id and created_at fields both should return the minimum):
select t.content, min(t.id), min(ut.created_at)
from tweets t
inner join user_tweets ut on t.id = ut.tweet_id
inner join followee_follower ff on ut.user_id = ff.follower_id
where ff.followee_id = 1
group by t.content
order by min(ut.created_at)
Related
I have a table called followers and I want to be able to find the current users followers, display that list, and then compare those values against another user ID to see if they are following them or not from that same table
This is the table I'm using currently to get the list of followers for a specific user:
followers
-------
followId - primary key, the unique id for the follow relationship
userId - the user that is following someone
orgId - that someone that the user is following
I tried using a union query but I wouldn't want to due to performance reasons (table may contain high volume of records) and because it isn't scalable (I think)?
The expected output should be the list of orgId's for which the user(the user I am checking against) is following, and another column that shows whether my user(my userId that I provide) is following that orgId value (i.e a following column).
Hmmm, if I understand correctly, you have two users and you want to know which orgs followed by the first are also followed by the second:
select f.orgid,
(exists (select 1
from followers f2
where f2.userId = $seconduserid and
f2.orgid = f.orgid
)
) as seconduserflag
from followers f
where f.userId = $firstuserid
I've looked at other examples of "data from one table not in other" SQL but still can't figure this out.
Table "pictures" contains:
"id", an auto increment ID number for this picture
"owner", an ID number referring to a unique user
Table "ratings" contains:
"picture", a reference to an entry in the "pictures" table
"userby", an ID number referring to a unique user
I want to select all pictures which have no entry in the ratings table by a specific user AND where the picture owner is not that user.
For example I might want to select all pictures which user 5 has not rated and is not the owner of.
Usually this would be a join between pictures and ratings and check if the ratings record is null, but I can't seem to get the addition of doing it only for specific users right.
How can I do this? I want to avoid sub-selects if possible. Thank you.
You need to add the additional checks to the join predicate and not in the where clause.
So something like
SELECT *
FROM pictures p LEFT JOIN
ratings r ON p.ID = r.PictureID AND r.UserID = 5
WHERE r.ID IS NULL
AND p.OwnerID <> 5
Have a look e this example
SQL Fiddle DEMO
select *
from pictures as p
where p.owner <> 5
and not exists(select * from ratings where picture = p.id and userby = 5)
first select pictures which is not owned by user p.owner <> 5
then search ratings for that picture by user exists(subquery)
use not if need picture for which no rating shoul exists
Unfortunately result you need could not be produced by 1 step combination (without subselect), because to do so an operation required, that can combine something existent (any picture not owned by user ) with something nonexistent ( missing rating by user ).
If there were some table containing fact that user did not rate some picture, then it would be possible! SQL can operate with things that exists only. That is what not exists(subquery) do - it realizes fact that there are no ratings given by user to a picture.
I am having a database design issue and i'm still pretty new to MySQL so I thought I would ask here. What would be the best way to get data for a chronological feed from multiple tables? For example a user does many things, they vote, comment, rate, ask questions. I save all this information in their respective tables "tblVote", "tblRate" etc, now the tricky part. a user can follow a user or many, so say you follow 3-4 people. Following allows you to see their interactions, voting, rating, commenting, asking questions etc in your feed (like facebook or something similar).
What would be the best way to get all the information from all 5 tables for every person they follow and then sort all of that chronologically? I Am assuming my current method (foreach follower grab all votes, comments, ratings etc and sort all would be terrible)
My working theory, so my working idea is to create a Interaction table, that has a column for the users id, the id of the other tables entry, and a type reference. so for example
User ID | InteractionID | Type
9 1232 Comment
10 80 Rating
9 572 Vote
Then you could just go ahead and grab all Interactions for each of the people they follow, sort that and then say grab the top 10? and query the individual databases to get the full info (time of comment, text of comment etc)
A many to many relationship exists between User and Follower. Since, Follower is also another user, this becomes a recursive many-to-many. When you decompose this relationship, you get a Association table or a gerund.
User_Follower {id, userid_fk, followerid_fk}
Both the userid_fk and followerid_fk are referencing to the User table.
Now, I am assuming you have a One-to-many relationship between User-tblRate, User-tblVote, User-tblPost etc.
So, you can write a join something like this:
select p.postTitle, p.postTag, ...,
c.commentId, c.commentData, ...
from (tblUser u INNER JOIN tblPost p
ON (p.userid = u.userid)) INNER JOIN tblComment c
ON (c.userid =
u.userid)
where u.userid in
(select userid_fk from user_follower where followerid_fk = 100)
orderby p.datetime_col ASC, c.datetime_col ASC
LIMIT 10;
100 is the user you want to get the information for.
The idea is that you just have one association table linking the User and Follower, then use simple joins to get the data for all the followees
I have two tables gcm_users and vechicle_master with me.
gcm_users has session id named ID which is generated automatically*(A_I Primary Key)* when user registers.I use this session id in my query to identify the user at time of log in.
requirement - i want to show all the vehicle details from vehicle_master table which are related with the user from the gcm_user table.
NOTE:
when a user logs in, he should only see his own vehicle details.
Try using JOIN you can do like, put your user_id in place of 1
SELECT a.*
FROM vehicle_master a
JOIN gcm_users b
ON a.registration_no = b.registration_no
WHERE user_id = 1
Sir,
The concept of my project is ,the logged user can upload three different photos and the deatils are stored in b_photodetails table and the fields are(id,photoid,student_id,userid,count,likes,subdate ) idas1,2,3...ect photoid means the name of the store photo file userid and count is the the number of photoes uploaded ie 1,2 and 3anly.and likes is the total number of likes for each photos.And i Have another table like_master containing the like details and the fields are(like_id,userid, liked_date) ,the like id in this table is same as id in the b_photodetails table ,and the liked_date is the date in which the photo is liked.So i need to get the number of likes between two particular
dates.Please help me to frame a query to solve this in MySQL.
For eg:If we click a like for where id=1,the likes in b_photodetails will be 1 and the like_master table will be(like_id,userid, liked_date) (1,userid eg:sree,2014-01-28)
I don't really know for sure what you are asking, but, here is my stab in the dark:
select sum(likes) from like_master where liked_date between 'date1' and 'date2';
or possibly
select sum(lm.likes)
from b_photodetails as b
right join like_master as lm
on b.userid = lm.userid
where lm.liked_date between 'date1' and 'date2';
I don't understand much what you are asking but may be it is like this
Select b.*,(SELECT COUNT(like_id) from like WHERE b.id = like.photo_id) as total_likes FROM b.photodetails