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.
Related
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.
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
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.
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
Here's what I want to accomplish:
Select all rows from table "posts" while also fetching linked entities, such as the author (from table "users") and the names of the categories the post belongs to (from table "categories").
These are my two queries so far:
This one fetches the posts:
SELECT
posts.*
, users.authorName AS author
FROM posts
INNER JOIN users
ON users.id = posts.author
And this one fetches a comma separated list of categories for a specific post:
SELECT
GROUP_CONCAT(categories.category) AS categories
FROM categories
INNER JOIN post_category
ON post_category.categoryID = categories.id
WHERE
post_category.postID = ?
The two queries on their own work fine.
Naturally when the two are combined, I wouldn't need the WHERE clause of the second query.
I tried using the second query as a sub-query within the first one's SELECT clause, but that fetched a comma separated list of ALL categories for ALL posts. I want only the categories for the post I'm currently iterating over.
Any help would be greatly appreciated, and I apologize if any of this is unclear - it's hard enough for me to think about, let alone describe to other people ;)
Something like this:
SELECT posts.*, users.authorName AS author,
GROUP_CONCAT(categories.category) AS categories
FROM posts, users, categories, post_category
WHERE users.id = posts.author
AND post_category.categoryID = categories.id
AND post_category.postID = posts.id
GROUP BY posts.* /* list actual columns here */, author
Or did I miss something?
I think your subquery approach should work fine, but you still need the where clause in your subquery. How else would MySQL know which rows to retrieve? Try:
SELECT posts.*, users.authorName AS author,
(SELECT GROUP_CONCAT(categories.category)
FROM categories
INNER JOIN post_category ON post_category.categoryID = categories.id
WHERE post_category.postID = posts.postID) AS categories
FROM posts
INNER JOIN users ON users.id = posts.author