简体   繁体   中英

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

  1. 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.

  2. 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.

  3. 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`

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM