You know how the Facebook home feed lists all the recent posts? It shows the user that posted, their actual post and then the first few comments attached to that post. That's what I'm trying to achieve, but I'm having a hard time building a single query that can gather all that data.
I have 3 tables: Uses, Posts and Comments. Each has a unique ID, but they reference each other's IDs. i.e, the Comments table has columns for the user_id of the user who posted and the post_id of the post it is attached to.
At the minute I'm querying SQL to gather all the posts. I join my Users and Comments tables to learn the Username of the poster and a total of how many comments the post has, like so:
$query = "
SELECT `posts`.`id`,`posts`.`message`,`posts`.`link`,
`posts`.`posted`,`posts`.`category`,`posts`.`user_id`,
`users`.`username`,
count(`comments`.`id`)
FROM `posts`
INNER JOIN `users`
ON `posts`.`user_id`=`users`.`id`
JOIN `comments`
ON `comments`.`post_id`=`posts`.`id`
WHERE `posts`.`group_id` = '$id'
AND `posts`.`category`='$filter'
GROUP BY `posts`.`id`
ORDER BY `posts`.`posted`
DESC
";
But instead of finding how many comments a post has, I would instead like to read the first few posts. Can anyone think of a way to achieve this with just the one query?
You can use the LIMIT clause to the the "first" posts. By making the "first posts" a subquery and then joining in the comments you can get everything in a single query. The comments should be left-joined in case of posts with no comments.
Notes:
This query is untested, but it should be close.
This will get all comments for the first few posts, so you'll need to limit the display of "max 3 comments per post" using the front-end display code.
It may be possible to limit comments to 3 per post within this query using variables, but that's not something I know how to do.
Here's the query:
SELECT
FirstPosts.id,
FirstPosts.message,
FirstPosts.link,
FirstPosts.posted,
FirstPosts.posts,
FirstPosts.user_id,
FirstPosts.username,
comments.<< your comment column >>
FROM (
SELECT `posts`.`id`,`posts`.`message`,`posts`.`link`,
`posts`.`posted`,`posts`.`category`,`posts`.`user_id`,
`users`.`username`
FROM `posts`
INNER JOIN `users`
ON `posts`.`user_id`=`users`.`id`
WHERE `posts`.`group_id` = '$id'
AND `posts`.`category`='$filter'
ORDER BY `posts`.`posted` DESC
LIMIT 20) FirstPosts
LEFT JOIN comments ON FirstPosts.id = comments.post_id
ORDER BY FirstPosts.Posted, comments.<< column you use to determing comment order >>
If you determine comment order by a date or sequence, you'll have to ORDER BY FirstPosts.Posted, comments.whatever DESC.
Hope this helps!
Related
$query = mysqli_query($conn, "SELECT BLOGGER_URL, COUNT(*) as NUM FROM Blog_Posts GROUP BY URL ORDER BY NUM DESC");
I'm using this query to return rows of data ordered based on the number of posts that a blogger has made. Each post has a blogger url ascribed to it, so I'm counting the number of blogger urls to determine the count.
I'm trying to order some rows based on the the number of posts made by a a blogger but right now the query only returns values that have a count of 1 or more. So Bloggers with no posts are not returned.
How can I edit the query to return ALL the bloggers in order?
Thanks, I'm pretty new to databases in general.
EDIT:
I have two tables relevant here: a bloggers table with a primary key blogger url and a blog posts table that uses the blogger url as a FK. The blog posts refer to a given blogger in the bloggers table
You should join your query to the users table so that you get a count of all users not just those with posts. I don't know your table structure, but you can do it in the following basic way.
SELECT Blog_Users.userid, COUNT(Blog_Posts.*) as NUM
FROM Blog_Users
LEFT OUTER JOIN Blog_Posts ON Blog_Posts.BLOGGER_USERID= Blog_Users.userid
GROUP BY Blog_Users.userid ORDER BY NUM DESC
It's normal that you have a count of 1 or more, cause the Bloggers that have not post does not exist in Blog_Post table, so if you want them returned, just join your Bloggers Table in the query with a left join.
Hope this heleped you
I’ve been creating a database called news which contains few tables with different information in them, articles employees, pictures etc. There is two things which I’m trying to do, first is to get the three most commented articles and they need to be in order with the one with most comments first.
This is the code that I’ve got which I’ve been working on. I have a table named comments which contains article ID etc.
SELECT a.ArticelID, a.preamble, a.Published, k.postcount FROM Article as a
INNER JOIN (
SELECT ArticelID,
count(*) AS postcount
FROM comments
GROUP BY ArticelID
) as k
on a.ArticelID = k.ArticelID
ORDER by k.postcount DESC LIMIT 3
But it feels kind of unineffective I would only like to simply use a Join and Group By but I can’t get it through my head how it is supposed to look.
The last thing I want to do is get relevant information from an article when it comes to what pictures the article has. I have two tables, one articles and one that is pictures, what I got so far is
SELECT PictureID, Filname, photographerName, ArticelID
FROM PictureID, Articel_Picture
WHERE PictureID IN (2);
But I keep on getting error that says “Column PictureID is ambiguous” how am I supposed to handle that message?
Your first query is fine, but you can also phrase it as:
SELECT a.ArticelID, a.preamble, a.Published, count(*) as CommentCount
FROM Article a join
comments c
on a.ArticleId = c.ArticleId
ORDER by CommentCount DESC
LIMIT 3;
For the second query, you need a join and aliases:
SELECT p.PictureID, p.Filname, p.photographerName, ap.ArticelID
FROM PictureID p join
Articel_Picture ap
on p.PictureId = ap.PictureId
WHERE ap.PictureID IN (2);
I'm having some problems with a query I'm writing. This seems like table structure that is very frequent so I'd love some help.
Let's say I have 3 tables similar to a facebook structure. Users, Wall Posts, and Comments. Users can make wall posts, and comment on other wall posts.
On a users page I would like to show a users wall posts and a count of how many comments that post has. This is what I have so far
I query the Wall Post table using the users id as an inner join to the User table. That gives me a result set of wall posts for that user's page. Then I loop through that result set, take the Wall Post id from each result set, and query the Comment table for the Count of comments for that Wall Post Id. This works, however I have to hit the db twice. Can anyone think of a way that I could do this with one query?
First Query Example:
SELECT wallPost.*, user.currentDefault, user.displayName, user.userName
FROM wallPost
INNER JOIN user ON user.id = wallPost.sourceUserId
WHERE wallPost.recipientId = ? ORDER BY wallPost.id DESC
Second Query Example:
SELECT COUNT(id) AS count
FROM comment
WHERE wallPostId = ?
I would add the count as a subquery and join the subquery to the main query
SELECT
wallPost.*,
user.currentDefault,
user.displayName,
user.userName,
wallpost_commentcount.total
FROM
wallPost
INNER JOIN user ON user.id=wallPost.sourceUserId
LEFT JOIN (SELECT wallPostId,COUNT(*) as total FROM comment GROUP BY wallPostId) as wallpost_commentcount ON (wallpost_commentcount.wallPostId=wallPost.id)
WHERE
wallPost.recipientId = ?
ORDER BY wallPost.id DESC
Please make sure you have an index on comment.wallPostId otherwise this query will take a long time.
I used the LEFT JOIN because you always want to get the wallPost even if there are no comments records yet
I hope itll be legal to post this as i'm aware of other similar posts on this topic. But im not able to get the other solutions to work, so trying to post my own scenario. Pretty much on the other examples like this one, im unsure how they use the tablenames and rows. is it through the punctuation?
SELECT bloggers.*, COUNT(post_id) AS post_count
FROM bloggers LEFT JOIN blogger_posts
ON bloggers.blogger_id = blogger_posts.blogger_id
GROUP BY bloggers.blogger_id
ORDER BY post_count
I have a table with articles, and a statistics table that gets new records every time an article is read. I am trying to make a query that sorts my article table by counting the number of records for that article id in the statistics table. like a "sort by views" functions.
my 2 tables:
article
id
statistics
pid <- same as article id
Looking at other examples im lacking the left join. just cant wrap my head around how to work that. my query at the moment looks like this:
$query = "SELECT *, COUNT(pid) AS views FROM statistics GROUP BY pid ORDER BY views DESC";
Any help is greatly appreciated!
SELECT article.*, COUNT(statistics.pid) AS views
FROM article LEFT JOIN statistics ON article.id = statistics.pid
GROUP BY article.id
ORDER BY views DESC
Ideas:
Combine both tables using a join
If an article has no statistics, fill up with NULL, i.e. use a left join
COUNT only counts non-NULL values, so count by right table to give correct zero results
GROUP BY to obtain exactly one result row for every article, i.e. to count statistics for each article individually
I am trying to build a sql query that I think it involves inner joins, but I can't figure it out. Here's the model:
There's two tables: comments, posts
Among many columns, there's the following important ones: comments.id, comments.user_id (owner), comments.post_id (reference to posts table), posts.id, posts.editor_id (which is the person, ie, owner of post).
I want to get the comments that either
1) current user has written, so something like:
select * from comments where user_id = <<current_user_id>>
2) (Assume current_user is editor). Get all comments that belong to a post that you have created.
This is what I have, but I get multiple lines....what am I missing?
select * FROM comments INNER JOIN posts ON comments.post_id = <<test_id>>
WHERE posts.editor_id = <<current_user.editor_id>>;
If you could give me a sql query that includes both of these things, that would be amazing.
Thanks!
Im not sure what you mean by "multiple lines" as you would return a row for each comment.
This should do it.
SELECT comments.*
FROM comments
INNER JOIN posts
ON comments.post_id = posts.id
WHERE posts.editor_id = #editorID;
I want to get the comments that either 1) current user has written, so something like: select * from comments where user_id = <>
That's correct. What's wrong with that?
Get all comments that belong to a post that you have created. This is what I have, but I get multiple lines
Well... you're supposed to. Looking at the schema it's indeed a post could contain many comments. The query given by tyrongower should do what you want.
Going with your requirements, this should work for you:
SELECT * FROM comments
WHERE (user_id = 1)
OR (post_id IN (SELECT id FROM post WHERE editor_id = 1))
In the above query "1" is used as a sample and should be replace with the id of current user.