Complex Mysql query to combine 3 tables Data? - php

I have a table in which I store followers, I have another table in which I store friendships
Now I have third table which stores stream data.
Its a social network, there are many reasons so I don't wish to have one table for follower & friendships (Means facebook subscriptions/friends)
Can someone presents a way how should I query streams table to pick activities of both friends & followings ?
Any help would be really appreciated, thank you
Here is simple Database Scheme, its not really like this but almost!
Okay here is database tables schema please,
Followers table.
Row_ID
User_ID
Following_User_ID
Friends Table
Row_ID
User_ID
Friend_ID
Stream Table
Row_ID
User_ID
Contents_ID
Time
Type

What are you looking for is probably best done as two distinct results sets... or a union of the two.
Select "friend" as src, author, post from friends f inner join streams s on s.author = f.id
union
Select "follower" as src, author, post from followers f inner join streams s on s.author = f.id
This is just some pseudo coding but it should give you an idea of how to proceed. Without knowing your database schema, this is the best I can offer.
Edit:
This might be what your looking for then
select user_id, contents_id, time from (
select user_id, contents_id, time
from followers f inner join stream s on s.user_id = f.user_id and f.user_id = "username"
union
select user_id, contents_id, time
from friends f inner join stream s on s.user_id = f.user_id and f.user_id = "username"
) order by time desc
This will return the data in time order, descending.

Related

PHP mySQL retrieve unique correct data from multiple tables

So i am making this webpage (for fun to practice web dev) where users can rate or comment on a movie. One page I have is where you click on the movie for full details and it lists all the ratings and comments (together if the user has commented by review and rated through a page called "reviewMovie"...which if they went this way the rating is mandatory, otherwise they can comment on this page "listMovieReviews").
The problem I am having is incorrect details when doing my queries
the discussion table stores: the discussion ID (primary key) the timestamp of the
comment, the comment, the user who made the comment, and the movie they commented
about.
the discussion table stores: the discussion ID (primary key) the timestamp of the
comment, the comment, the user who made the comment, and the movie they commented
about.
the rating table stores: the rating ID (primary key), the movie being rated, the
user who did the rating, and the rating score (out of 10)
So some examples of the combined data are:
User1 (user1) has rated "American Psycho" a 4/10 and has made a comment "comment1" on
it
User2 (admin..for testing purposes) has rated "American Psycho" a 8/10 and has made a
comment "comment2" on it
So on the page that lists the details of "American Psycho" and the ratings/comments I should have this list of ratings and comments:
<TIMESTAMP FOR COMMENT1> User1 Rating 4/10 "comment1"
<TIMESTAMP FOR COMMENT2> admin Rating 8/10 "comment2"
Using the following queries:
SELECT *
FROM discussion
INNER JOIN users ON discussion.userID = users.userID
WHERE discussion.movieID = <American Psycho's Movie ID>;
AND
SELECT *
FROM ratings
INNER JOIN movies ON ratings.movieID = movies.movieID
WHERE ratings.movieID = <American Psycho's Movie ID>;
I get this:
<TIMESTAMP FOR COMMENT2> admin Rating 4/10 "comment2"
<TIMESTAMP FOR COMMENT2> admin Rating 8/10 "comment2"
I have tried several other INNER JOINS with joining the table that stores user information and table that stores movies information but I keep getting mixed data
Also tried DISTINCT and UNION but still to no avail
Where am I going wrong??
Also first post so sorry If I have not been too clear, bad formatting, or not shown enough work but I am really really stuck
I assume:
A movie could have from 0 to n comments.
A movie could have from 0 to n ratings.
A user could rate a movie only once or none.
A user could comment a movie from 0 to n times.
Your queries are fine, maybe your problem is in your php code.
You have to account that a user maybe comment a movie several time and never rated it.
In second query you should JOIN with user (instead of with movie, because you do not get movie information) to get the user name.
Maybe you should display the info in two table: one for ratings and other for comments.
(You have to replace quotation marks by movie ID)
SELECT u.userName, r.score
FROM ratings AS r
INNER JOIN users AS u ON r.userID = u.userID
WHERE r.movieID = ?;
SELECT u.userName, d.commentTime, d.comment
FROM discussion AS d
INNER JOIN users AS u ON d.userID = u.userID
WHERE d.movieID = ?;
You could group all comments per user in one row this way (but I think this is not what you are looking for):
SELECT u.userName, GROUP_CONCAT(CONCAT(d.commentTime, ': ', d.comment) SEPARATOR '; ') AS comments
FROM discussion AS d
INNER JOIN users AS u ON d.userID = u.userID
WHERE d.movieID = ?
GROUP BY u.userName
I think do not have sense to make one query in this case, but if you want get all data in one query you could try something like this:
You will have a comment per row, so for example if a user make two comment you will have two rows for the same user with the same score.
First I get all user that comment or rating the selected movie and make a CROSS JOIN between movie and these users. Then I make a LEFT JOIN with discussion ON movieID and userID and another LEFT JOIN with ratings ON movieID and userID.
You need to make LEFT JOIN instead of INNER JOIN because if a movie do not have ratings or comments your result will be empty.
In SELECT clause you should list only the columns that you need.
SELECT *
FROM movies m
CROSS JOIN (SELECT d.userID
FROM discussion d
WHERE d.movieID = ?
UNION
SELECT r.userID
FROM ratings r
WHERE r.movieID = ?) AS u
LEFT JOIN discussion AS d ON m.movieID = d.movieID AND u.userID = d.userID
LEFT JOIN ratings AS r ON m.movieID = r.movieID AND u.userID = r.userID
LEFT JOIN users ON u.userID = users.userID
WHERE m.movieID = ?;
You need to join all three tables.
SELECT *
FROM movies AS m
JOIN ratings AS r ON r.movieID = m.movieID
JOIN discussion AS d ON d.userID = r.userID AND d.movieID = m.movieID
WHERE m.movieID = <American Psycho's Movie ID>
ORDER BY r.userID, d.timestamp
This will repeat the movie and rating information for each comment. You can remove those duplicates in the application code that displays the results. See How can i list has same id data with while loop in PHP? for an example of how to do this.
SELECT * FROM movies AS MOVIE
JOIN ratings AS RATING ON `RATING.movieID` = `MOVIE.movieID`
JOIN discussion AS DISCUS ON `DISCUS.userID` = `RATING.userID`
WHERE `MOVIE.movieID` = <SOME Movie ID>
ORDER BY `RATING.userID`, `DISCUS.timestamp`

Want to select data from different tables

I have two tables in database, named users(store user details) and posts(store post details). Now i want to get data from both tables. Like user_image from users and post description from post.
I am using this query
SELECT * FROM `users`AS u,`posts` WHERE u.user_id IN (SELECT user_id FROM `posts`)
But it returns duplicate data. I have 2 users and 3 posts but it returns 6 posts.
Try something like:
Select a.user_image, b.post_description from users as a join posts as b on a.user_id = b.user_id
Do an inner join & you shall get the desired result
In the above query a & b are alias for the two different tables. I you do not want to use alias you can also write it as users.user_image in your select statement.
Write the fields you want from both the tables in your select statements.
The below image will help you understand the inner join
Inner Join Circle for understanding
Use group by as below:
SELECT * FROM `users`AS u,`posts` WHERE u.user_id IN (SELECT user_id FROM `posts`) group by u.user_id
What about
Select * FROM user u right join posts p on u.id = p.user_id
?
if you want to get data from both tables you need to use joins.and you make sure the two tables are interlinked by primary keys
so use this can help
select user_image,post_description from users join posts on users.user_id=posts.user_id;

Complex MySQL Query, Multi Table - How Do I Write This Relational Query?

I'm having issues writing this query, it's an odd relation that I can't figure out. I'm wondering if it would be better to just use two mysql queries and merge the results with php?... Anyways.. so here we go.
Here's the tables we're using:
- media -
id
userId
accessKey
internalName
type
created
modified
- reposts -
id
userId
mediaId
created
- users -
id
username
Basically, what I want to do is get a result set of media items associated with the user who posted it, and then ALSO, in the same result set, include additional rows for media items that have been reposted, and then for reposted media items, instead of associating the media.userId of the media item for the username association, associate the reposts.userId as the username.
Here's a rough idea to illustrate, these two example queries below need to work as 1 to provide a combined result set.
SELECT media.*, users.username,
0 AS reposted
FROM media
LEFT JOIN users ON users.id = media.userId
SELECT media.id, media.accessKey, media.internalName, media.type, media.modified, users.username, reposts.userId, reposts.created,
1 AS reposted
FROM reposts
LEFT JOIN media ON media.id = reposts.mediaId
LEFT JOIN users ON users.id = reposts.userId
How would I go about doing this? Or would I be better off using 2 queries and merging the results with PHP?
You can use UNION in your query, but UNION requires the same number of columns (and same data type if I recall correctly) on both queries:
(SELECT media.id, media.accessKey, media.internalName, media.type, media.modified, users.username, users.id, media.created,
0 AS reposted
FROM media
LEFT JOIN users ON users.id = media.userId)
UNION
(SELECT media.id, media.accessKey, media.internalName, media.type, media.modified, users.username, reposts.userId, reposts.created,
1 AS reposted
FROM reposts
LEFT JOIN media ON media.id = reposts.mediaId
LEFT JOIN users ON users.id = reposts.userId)

facebook type wall post script

I have two mysql tables members_tbl and post_tbl
members_tbl:
id|userName |fname |lname |friendArray
post_tbl:
postId| memId | thePost |postDate
now, I'm trying to display post from user id and from his friendArray.
please let me know how to do it (still new to php)
Since MySQL lacks an explode function, you either need to create a relation table and use joins, or use multiple queries with php processing inbetween. I strongly recommend the relational approach as it conforms to database standards (normalization) much more than the alternative and is easier to implement.
You need a third table, which describes the relation between two friends, I.E.
friends_tbl
user1_id | user2_id
With a primary key on user1_id and user2_id (thereby preventing duplicates). For every friend relationship, I.E. user 1 is friends with user 2, there is one row in this table. You can then get the listing you want with the following query.
SELECT p.*, u.*
FROM posts_tbl p
INNER JOIN members_tbl u
ON u.id = p.memId
WHERE u.id IN (
SELECT user2_id AS id
FROM friends_tbl
INNER JOIN members_tbl
ON (user1_id = id)
WHERE members_tbl.id = $id
UNION
SELECT user1_id AS id
FROM friends_tbl
INNER JOIN members_tbl
ON (user2_id = id)
WHERE members_tbl.id = $id
)
ORDER BY p.postDate
SQLFiddle of the above.
create a different table for your friend-relations and then join this table in your SQL.

Using the MySQL select statement

I would like to select the posts from users based on who the logged in user is following. What would I need to do? How do I use two different tables with one SELECT statement? I don't even know where to start.
I have 3 tables:
users
posts
followers
Thanks.
SELECT p.*
FROM followers f
JOIN posts p
ON p.author = f.following_id
WHERE f.user_id = $logged_in
ORDER BY
p.post_date DESC
I had to make up the field names as you haven't provided them.
Selecting from two tables is done using JOINs
http://dev.mysql.com/doc/refman/5.0/en/join.html
basically you select from two tables and define JOIN condition.
Assume you have two tables:
users with columns: user_id, user_name, online_state
posts with columns: post_id, user_id (user who posted this post), title, message
SELECT p.title, p.message FROM users u JOIN posts p ON u.user_id = p.user_id WHERE u.online_state = 'online'
join condition should be after ON, non-join condition after WHERE
I would go with the Join query as Quassonoi suggested in his answer, If you want to try an alternate solution, you can do it with subquery like this
SELECT P.PostId,P.Title,P.Body
FROM Post P WHERE P.CreatedById
IN (
SELECT FollowerID from Followers WHERE USER_ID=3
)
Replace 3 with the current user id. Assuming your table structure is something like this.
POST
PostId (int)
Title
Body
Followers
UserId (int)
FollowerId (int)

Categories