I have a users table, books table and authors table. An author can have many books, while a user can also have many books. (This is how my DB is currently setup). As I'm pretty new to So far my setup is like bookview.php?book_id=23 from accessing authors page, then seeing all books for the author. The single book's details are all displayed on this new page...I can get the output to display the user ID associated with the book, but not the user name, and this also applies for the author's name, I can the author ID to display, but not the name, so somewhere in the query below I am not calling in the correct values:
SELECT users.user_id,
authors.author_id,
books.book_id,
books.bookname,
books.bookprice,
books.bookplot
FROM books
INNER JOIN authors on books.book_id = authors.book_id
INNER JOIN users ON books.book_id = users.user_id
WHERE books.book_id=" . $book_id;
Could someone help me correct this so I can display the author name and user name both associated with the book! Thanks for the help :)
I think the right join conditions would be something like (changes bolded)
SELECT users.user_id,
**users.user_name,**
authors.author_id,
**authors.author_name,**
books.book_id,
books.bookname,
books.bookprice,
books.bookplot
FROM books
INNER JOIN authors on books.**author_id** = authors.**author_id**
INNER JOIN users ON books.**user_id** = users.user_id
WHERE books.book_id=" . $book_id;
Or you can use the less verbose syntax for simple inner joins.
SELECT users.user_id,
users.user_name,
authors.author_id,
authors.author_name,
books.book_id,
books.bookname,
books.bookprice,
books.bookplot
FROM books, authors, users
where books.author_id = authors.author_id
and books.user_id = users.user_id
and books.book_id=" . $book_id
It would help if I added the name fields into the select query :D
These two joins together:
INNER JOIN authors on books.book_id = authors.book_id
INNER JOIN users ON books.book_id = users.user_id
also imply authors.book_id = users.user_id which, on the face of it, makes no sense. Surely the code you've posted is not the code you're actually using...?
Related
Newbie here.. Here's what I'm trying to do.
I have a Posts table with the following columns
id, userid, bodyText, date
and I have another table for users users.
When users submit a post, the user-id saves into the "posts" table under "userid". Well, I want to display that users information, such as name and picture, on the posts using the "userid" to get each users information so that their name and picture shows along with the post they submitted.
Sorry if I'm not being clear, english is not my first language and like I said, I'm new at this and still trying to learn.
I had it where when they submit the post, their name and picture also saves into the "posts" table but I want to change it because if the user updates their name or picture, it will still show the name and picture they had when they submitted the post. I want their name and picture to update on the posts if they update their information on the users table.
What you are asking about is a JOIN. In general the Join will look like
SELECT p.id. p.bodyText, p.date, u.name, u.picture FROM posts as p INNER JOIN users as u ON p.user_id = u.id where p.id = 123;
This will select the post with the ID 123 from the posts table and joins the users information from the users table based on the user_id columns value from the posts table.
In Syntax this could be something like
$sth = $dbh->prepare("SELECT p.id. p.bodyText, p.date, u.name, u.picture FROM posts as p INNER JOIN users as u ON p.user_id = u.id where p.id = ?");
$sth->execute(array(123));
$red = $sth->fetchAll();
I'm using MySQL. I have 3 tables I'm trying to connect in a query and I can't see what I'm doing wrong with the following query:
Table 1: books (list of book information)
Table 2: bookshelf (list of books a member owns)
Table 3: book_reviews (list of book reviews)
I want to generate a list of all books a user has in their bookshelf, as well as any reviews they have made. The following query gives me a list only of books the user has reviewed; I want all of their books. I thought the second LEFT OUTER JOIN would do this - connecting the bookshelf titles to the book reviews titles, but I don't get any books with no reviews (there should be lots). Removing the second JOIN statement (and putting bookshelf in the FROM statement) allows me to get a list of titles with no reviews, but it shows all book reviews by all users.
SELECT books.title, book_reviews.comments
FROM books
LEFT OUTER JOIN book_reviews ON books.ID = book_reviews.book_id
LEFT OUTER JOIN bookshelf ON book_reviews.user_id = bookshelf.user_id
WHERE bookshelf.book_id = books.ID
AND bookshelf.user_id =1
I imagine I'm missing something very obvious, but I've been reading about joins and going over my logic and I'm blind to it. Thanks to anyone who can help me see...
Try this:
SELECT books.title, book_reviews.comments
FROM bookshelf
LEFT OUTER JOIN books ON books.ID = bookshelf.book_id
LEFT OUTER JOIN book_reviews ON book_reviews.book_id = books.ID
AND book_reviews.user_id = bookshelf.user_id
WHERE bookshelf.user_id =1
I've spent a bit of time researching this on here and the mysql site but I'm a bit confused on two things: which sort of join to use and how (or if) to use an alias.
The query:
SELECT forum_threads.id, forum_threads.forum_id, forum_threads.sticky,
forum_threads.vis_rank, forum_threads.locked, forum_threads.lock_rank,
forum_threads.author_id, forum_threads.thread_title, forum_threads.post_time,
forum_threads.views, forum_threads.replies, users.username AS author_username
FROM forum_threads LEFT JOIN users ON forum_threads.author_id = users.id
WHERE forum_threads.forum_id=XXX
Now that query currently finds all threads from the given forum and joins the threads author id to the username table. I also have lastpostid which I'd also like to include in that query and join again on the users table so I can get the username for the last poster too.
I tried adding:
LEFT JOIN users ON threads.lastpostid = users.username
but that just results in an alias error as users isn't unique.
I also tried using both an alias on the main query and on the second join but it keeps giving me missing field errors.
Could someone give me a point in right direction please?
Yes, you need a different alias each time. Every time you refer to the table in the query you should use the approprate alias.
SELECT
forum_threads.id,
-- etc...,
forum_threads.replies,
u1.username AS author_username
u2.username AS last_post_username
FROM forum_threads
LEFT JOIN users u1 ON forum_threads.author_id = u1.id
LEFT JOIN users u2 ON threads.lastpostid = u2.username
WHERE forum_threads.forum_id=XXX
I need to build an activity feed to go on each users profile page showing what they have been doing on the site.
There is three tables: comments, ratings, users
I want the feed to include the comments and ratings that the user has posted.
in the comments and ratings table it stores the user id of the user who posted it, not the username, so in for each item in the news feed it needs to select from the users table where the user id is the same to retrieve the username.
All the entries in the feed should be ordered by date.
Here is what ive got even though i know it is not correct because it is trying to match both with the same row in the users table.
SELECT comments.date, comments.url AS comment_url, comments.user_id, ratings.date, ratings.url AS rating_url, ratings.user_id, users.id, users.username
FROM comments, ratings, users
WHERE comments.user_id=%s
AND comments.user_id=users.id
AND ratings.user_id=%s
AND ratings.user_id=users.id
ORDER BY ratings.date, comments.date DESC
JOIN. It seems you know that, but here's how:
SELECT * FROM comments LEFT JOIN users ON comments.user_id = users.id
Thus, as far as I can tell, you're trying to order two separate things at the same time. The closest I think I can come up with would be something like:
(SELECT comments.date AS date, users.username AS name, comments.url AS url CONCAT('Something happened: ',comments.url) AS text
FROM comments LEFT JOIN users ON comments.user_id = users.id
WHERE users.id = %s)
UNION
(SELECT ratings.date AS date, users.username AS name, ratings.url AS url CONCAT('Something happened: ',ratings.url) AS text
FROM comments LEFT JOIN users ON comments.user_id = users.id
WHERE users.id = %s)
ORDER BY date DESC LIMIT 0,10
Note that the columns of both parts of the union match up. I'm pretty sure that that is required for something like this to work. That's why I have that CONCAT statement, which lets you build a string that works differently between ratings and comments.
I am trying to create a news page for a website I am working on. I decided that I want to use correct MySQL queries (meaning COUNT(id) and joins instead of more than one query or num_rows.) I'm using a PDO wrapper, that should function fine, and this still fails when run directly through the MySQL CLI application.
Basically, I have 3 tables. One holds the news, one holds the comments and one holds the users. My aim here is to create a page which displays all (will paginate later) the news posts titles, bodies, authors and dates. This worked fine when I used a second query to get the username, but then I decided I'd rather use a JOIN.
So what's the problem? Well, I need two joins. One is to get the author's username and the other to get the number of comments. When I simply go for the author's username, all works as expected. All the rows (there are 2) in the news table are displayed. However, when I added this second LEFT JOIN for the comments row, I end up only receiving one row from news (remember, there are 2,) and COUNT(comments.id) gives me 2 (it should display 1, as I have a comment for each post.)
What am I doing wrong? Why is it only displaying one news post, and saying that it has two comments, when there are two news posts, each with one comment?
SELECT news.id, users.username, news.title, news.date, news.body, COUNT(comments.id)
FROM news
LEFT JOIN users
ON news.user_id = users.id
LEFT JOIN comments
ON comments.news_id = news.id
Also, just to be sure about one other thing, my left join to comments is the correct way to get all posts regardless of whether they have comments or not, correct? Or would that be a right join? Oh, one last thing... if I switch comments.news_id = news.id to news.id = comments.news_id, I get 0 results.
You're missing a GROUP BY clause:
SELECT news.id, users.username, news.title, news.date, news.body, COUNT(comments.id)
FROM news
LEFT JOIN users
ON news.user_id = users.id
LEFT JOIN comments
ON comments.news_id = news.id
GROUP BY news.id
The left join is correct. If you used an INNER or RIGHT JOIN then you wouldn't get news items that didn't have comments.
To display the all details for each news post title ie. "news.id" which is the primary key, you need to use GROUP BY clause for "news.id"
SELECT news.id, users.username, news.title, news.date,
news.body, COUNT(comments.id)
FROM news
LEFT JOIN users
ON news.user_id = users.id
LEFT JOIN comments
ON comments.news_id = news.id
GROUP BY news.id