Really simple MySQL JOIN not working? - mysql

What am I doing wrong? Seriously confused.
SELECT *
FROM photos
WHERE user_id = 1
JOIN photos_albums ON photos_albums.photo_id = photos.id
The context is, I have a table to store photos, and another table to store photo albums (not shown). I also have a cross-referencing table photos_albums to store which photos are in which albums.
I get given a Syntax Error. eh?
Thanks!
Jack

The WHERE clause must come after the joins, e.g.
SELECT *
FROM photos
INNER JOIN photos_albums
ON (photos_albums.photo_id = photos.id)
WHERE user_id = 1
See manual page for SELECT syntax for all the gory details.

The where should come at the end; try modifying it like this:
SELECT *
FROM photos p JOIN photos_albums pa ON pa.photo_id = p.id
WHERE p.user_id = 1

Related

How can i count all likes from another tabel?

I already made it to the point that my SQL reutrns all posts from tbl_posts when they have at least one like. BUt now i am wondering how i can get it work so it returns all posts even when they have no likes. The likes are stored in tbl_posts_likes via foreign keys (post_id, user_id as columns in tbl_posts_likes). My SQL looks like this at the moment:
SELECT tbl_posts.*,tbl_users.name,COUNT(tbl_posts_likes.user_id) AS likes
FROM tbl_posts
INNER JOIN tbl_users ON tbl_posts.user_id = tbl_users.id
LEFT JOIN (SELECT * FROM tbl_friends fr WHERE fr.friend_id = '1') AS fr ON tbl_posts.user_id = fr.user_id
RIGHT JOIN tbl_posts_likes ON tbl_posts_likes.post_id = tbl_posts.id
WHERE tbl_posts.user_id = '1' OR tbl_posts.user_id = fr.user_id
ORDER BY tbl_posts.created_at DESC
It would be nice if you can help me out because i am searching since days to get a working SQL set up :/
Greetings from Germany!
You needed to group by tbl_posts.id to get the results per post.
If you dont do this all results are merged into one row.
a fiddle with the results per post, if it has no likes the result is 0.
SELECT tbl_posts.*,tbl_users.name,COUNT(tbl_posts_likes.user_id) AS likes
FROM tbl_posts
INNER JOIN tbl_users ON tbl_posts.user_id = tbl_users.id
LEFT JOIN tbl_posts_likes
ON tbl_posts.id = tbl_posts_likes.post_id
group by tbl_posts.id
A nice way to find solutions for problems like this:
Simplify the problem by first just getting the posts with a count of likes only. later add the other joins but first focus on getting the most basic result.

Complex SQL query, checking column values in multiple tables

I have a pretty huge SQL query to check for notifications, and I have several different types of notifications in the table, IE: posts, likes, comments, photoComments, photoLikes, videoLikes, etc. (Always adding more to it) And I have come into a problem, I'm not really sure how to best do this anymore. Thus far the way I have done it is working perfectly, and really quite easy to add to, however this one notification Type I have to check more than just one other table, I have to check two others and I haven't been able to get it to work.
So here it is: (This is only one part of my huge query, the only relevant part really)
n.uniqueID = ANY (
SELECT photos.id
FROM photos INNER JOIN posts ON (photos.id=posts.post)
WHERE photos.state=0
AND posts.state=0
AND posts.id = ANY (
SELECT likes.postID FROM likes
INNER JOIN posts ON (posts.id=likes.postID)
WHERE likes.state=0 AND posts.state=0
)
)
So basically all I really need to do is check the state columns in each table because that says whether or not it is deleted or not (if it's not 0 then it's deleted and shouldn't be returned)
So it would be like:
IF photos.state=0 AND posts.state=0 AND likes.state=0 return it.
n.uniqueID, posts.post, and photo.id will all be the same
value.
posts.id and likes.postID will also be the same value.
My issue is that it doesn't seem to be checking the likes.state, I don't think.
I think you just want to join the three tables together in a single query:
n.uniqueID = ANY (
SELECT photos.id
FROM photos INNER JOIN
posts
ON photos.id=posts.post inner join
likes
on posts.id = likes.postId
WHERE photos.state=0 and
posts.state=0 and
likes.state = 0
)
Your logic is not to return when there is a like or post with the state of 0. It seems to be that all the likes and posts have a state of zero. For this, do an aggregation with a having clause:
n.uniqueID = ANY (
SELECT photos.id
FROM photos INNER JOIN
posts
ON photos.id=posts.post inner join
likes
on posts.id = likes.postId
where photos.state = 0
group by photos.id
having MAX(posts.state) = 0 and MAX(likes.state) = 0

SQL Select -> product -> comments -> user

thanks for yout time helping on this ;)
I'm new to SQL and wish to solve somethign in just one query and i dont know how to do it.-
Basically I've a table of products, a table of users and a table of comments, linked by products.id -> comments.pid and user.id -> comments.uid ,
i wish to know what is the best practice to create just 1 query and get all products with child comments, including username.
Learn about SQL joins:
SELECT *
FROM products
LEFT JOIN comments ON products.id = comments.pid
LEFT JOIN user ON user.id = comments.uid
learning joins is the best way to solve such a problem
Explanation
what we are trying here to do is create a virtual table which fetches records based on some relations.
I have created three tables here
product
user
comments
and there is a relation set between the
product and the comments table - using product.id and comments.prod_id
user and the comments table - using user.id and comments.user_id
Now you can use join to filter the results
SELECT product.id,user.name,comments.DATA
FROM comments
LEFT JOIN product ON comments.prod_id = product.id
INNER JOIN USER ON comments.user_id = USER.id;
or if you don't want to use join you can simply create a relation
but please do note that using joins is the best possible way to do it
SELECT product.id,USER.name,comments.DATA
FROM product,USER,comments
WHERE product.id = comments.prod_id AND USER.id = comments.user_id;
you can check the results here
SqlFiddle
Istead of using JOIN you can try this,
select p.id,u.name,c.data
from products as p,user as u,comment as c
where p.id = c.pid and u.id = c.uid;

Confused on a somewhat complex LEFT/RIGHT JOIN query

thanks for taking the time to read this.
Essentially I have 3 tables. Posts, Follows, Artists. What I am trying to do is pull all the 'Posts' from 'Artists' that the user 'Follows'. I am passing the user_id in, and trying to pull data from 'Posts' and 'Artists'
Posts /* the posts table */
id
body
artist_id
timecode
Follows /* the follows table */
id
artist_id
user_id
Artists /* the artists table */
id
name
So, my basic query starts out like this:
SELECT Posts.id,Posts.body,Posts.timecode,Artists.id AS artist_id,Artists.name
FROM Posts,Artists
LEFT JOIN Artists
ON Posts.artist_id = Artists.id
Now this is where I start to get confused. I am guessing that I need another JOIN statement on the "Follows" table so that I limit the returned results to rows that have a "follows" entry with both the user_id and artist_id.
ie:
RIGHT JOIN Follows
ON Posts.artist_id = Follows.artist_id
WHERE Follows.user_id = :userid
My problem is that I'm not really even sure how to write this properly, although I feel like i'm on the right track here... sorta
ANY help would be much appreciated!!! Thanks.
EDIT Please note I am pulling data from both the Posts and Artists tables, not just the Posts table. Not sure if this makes a big difference.
I can't see that you need an outer join, standard SQL inner joins should return the set you want. You have to trust SQL to go find all the rows you're interested in.
SELECT
p.*
FROM
posts p,
artists a,
follows f
WHERE
f.user_id = :userid AND
a.id = f.artist_id AND
p.artist_id = a.id
;
SELECT p.id,p.body,p.timecode,a.id AS artist_id,a.name
FROM Posts p
INNER JOIN Follows f ON p.artist_id = f.artist_id
INNER JOIN Artists a ON f.artist_id = a.id
WHERE f.user_id = X
Haven't checked the syntax I hope it is ok.

Count Number of UnViewed Posts

I have a db structure like:
posts
id
title
content
users
id
....
post_reads
post_id
user_id
How can I count the number of posts for which a particular user with an id say, x does not have a read record.
My SQL query currently looks like:
SELECT COUNT(posts.id) AS c
FROM `posts`
LEFT JOIN `post_reads` ON (`posts`.`id` = `post_reads`.`post_id`)
LEFT JOIN `users` ON (post_reads.user_id = `users`.`id` AND post_reads.user_id = x)
WHERE users.id IS NULL
AND post_reads.user_id IS NULL
I know I'm doing something wrong, although I'm not sure what that is.
This should to the trick
SELECT COUNT(posts.id) AS c
FROM posts
LEFT JOIN post_reads ON posts.id = post_reads.post_id AND post_reads.user_id = x
LEFT JOIN users ON post_reads.user_id = users.id
WHERE users.id IS NULL
Note that if you're not interested in doing anything with table users you can shorten this query to:
SELECT COUNT(posts.id) AS c
FROM posts
LEFT JOIN post_reads ON posts.id = post_reads.post_id AND post_reads.user_id = x
WHERE post_reads.user_id IS NULL
The first join you were doing is really an inner join, because it will never 'misfire'.
The second join will sometimes misfire, because you have the extra condition in there.
Therefore using the post_reads.some_id is null will never be true.
In order for that to work you'd have to repeat the AND post_reads.user_id = x in that join condition as well, but putting it in twice is silly and not needed, once will do.
PS don't forget to replace the 'x' with something more useful :-)
I tried this a few ways just using JOINS/WHERE, but they tend to miss certain cases (i.e. you can exclude posts joined to a read record for the given user, but the posts' ids will still be returned if they also join to read records for other users).
The simplest way may be something like this:
SELECT COUNT(DISTINCT id)
FROM posts
WHERE id NOT IN (SELECT DISTINCT post_id FROM post_reads WHERE user_id = #x)
Also, note that I don't believe you need to surround identifiers in backticks unless they are MySQL keywords.