We have 2 tables: articles, comments.
The structure of this tables:
articles(article_id(PK), etc);
comments(comment_id(PK), article_id(FK)).
I need to get a list of the most commented articles.
I used the request:
SELECT articles.article_id, COUNT(comments.article_id)
FROM comments
INNER JOIN articles ON comments.article_id = articles.article_id AND comments.article_id = :article_id.
What should be the request to get an array of data with 3 most commented articles?
Is it really possible to do this with SQL?
You should be able to get what you want with this query:
SELECT articles.article_id, COUNT(comments.article_id) AS num_comments
FROM comments
INNER JOIN articles ON comments.article_id = articles.article_id
GROUP BY articles.article_id
ORDER BY num_comments DESC
LIMIT 3
If you just need the article id, then a join is not necessary:
SELECT c.article_id, COUNT(*) AS num_comments
FROM comments c
GROUP BY c.article_id
ORDER BY num_comments DESC
LIMIT 3
The query below will provide to you a list of articles and the number of comments for each of these articles ordering them in descending order of number_of_comments
SELECT articles.article_id, COUNT(comments.article_id) AS comment_count
FROM articles, comments
WHERE articles.article_id=comments.article_id
GROUP BY articles.article_id
ORDER BY comment_count DESC
there is an easier way, you can add 'n-comments' column on the article table and initialize it to zero, and with your function to submit a comment, update the value of the 'n-comments++' after every comment.
thin every article will contain the number of its comments, and it will be very easy to select the most commented articles by:
"SELECT article_id FROM articles ORDER BY n-comments DESC LIMIT 50"
I think it will be easier and faster, hope it can help
Related
I'm putting together a simple forum script with topics/posts. I'm trying to order topics by latest post and I've had some luck with the answer in the following question: MYSQL Order from another Table, but the problem I have is that some topics don't have any posts yet, so the query doesn't select those topics at all.
Current coding is:
SELECT DISTINCT forum.*
FROM forum
INNER JOIN forum_posts
ON forum.id = forum_posts.parent_id
GROUP BY forum.id
ORDER BY forum_posts.parent_id DESC,
forum_posts.time_created DESC
LIMIT ?,?
I want to tell the ORDER BY to order by forum.time_created if there are no matches in forum_posts.parent_id for a topic.
On a side note, I would also like to know how to put a WHERE clause into this query as well. I want to only get rows from forum table "WHERE access <= ?", but can't work out where to put that snippet in.
Any help much appreciated!
EDIT:
Target is to return topics (from forum table)
According to following details:
WHERE forum.access <= ?
LIMIT ?,?
ORDER BY
Latest Post From forum_posts table with forum_posts.parent_id matching on forum.id,
or forum.time_created
EDIT 2:
An example SQLfiddle with relevant data. This doesn't work as the order should really come out as 11,10,9,1,2
http://sqlfiddle.com/#!2/83535/2
Have a look at this: http://sqlfiddle.com/#!2/be909/1
Here's my final query:
SELECT forum.*, recent_forum_posts.time_created as latest_post
FROM forum
LEFT JOIN (SELECT MAX(forum_posts.time_created) as time_created, forum_posts.parent_id
FROM forum_posts
GROUP BY forum_posts.parent_id) AS recent_forum_posts
ON forum.id = recent_forum_posts.parent_id
WHERE forum.access > 2
ORDER BY recent_forum_posts.time_created IS NULL DESC,
recent_forum_posts.time_created DESC,
forum.time_created DESC
LIMIT 5
Essentially, the subquery (the bit in brackets after LEFT JOIN) selects the most recent post for each parent_id from the forum_posts table.
That is then LEFT JOINed (as we want to list all forum's even if there are no posts yet).
I have created a simple blog in php/mysql that show in homepage latest 100 posts and for every post show the comments's number.
This is the pseudocode:
Mysql query to get latest 100 posts.
While cicle:
Get title and body of each post.
Mysql query to get the comments's number of the post.
Database structure:
Post:
-id
-title
-body
-date
Comments:
-id
-id_post
-id_user
-body
-date
Is there a way to avoid 100 queries ?
It's a fairly straightforward query:
SELECT p.id, p.title, p.body. p.date, COUNT(c.id) AS comment_count
FROM Post p
LEFT JOIN Comments c ON p.id=c.id_post
GROUP BY p.id, p.title, p.body. p.date
ORDER BY p.id DESC
LIMIT 100
(Please note it's untested, take it as a starting point.)
I know it's a common believe that a database is nothing but a fancy file system and SELECT * FROM data is all the SQL you'll ever need to know but investing some time in learning basic SQL it's absolutely worth the effort.
You can write a sql query that JOINS both of your tables together, to return all of the information you want:
SELECT
p.id,
p.title,
p.body,
p.date,
COUNT(c.id)
FROM Post p
LEFT JOIN Comments c ON p.id = C.post_id
GROUP BY p.id, p.title, p.body, p.date
ORDER BY p.date DESC
LIMIT 100
Jeff Atwood has a great visual guide explaining how joins work.
We are effectively selecting the top 100 posts in date order, counting the total comments (if they exist - that's why we use a LEFT JOIN as otherwise, if we use an INNER JOIN, we will ONLY return posts that have comments).
We GROUP BY as that's how COUNT (and other aggregation functions like SUM and AVG work - we need to tell them what the rule is for counting/summing/averaging our rows.
We ORDER BY the post date, in DESCending order (latest first) to ensure we return posts in the order they were made.
The LIMIT 100 statement only returns the first 100 rows in MySql. Change it to any number you wish (a top 10, 50 etc) if you want to vary the number of posts in the summary.
The overall result is that you now have a result set that contains the post information, and the number of comments, all in one query. You can then display these results in your web application any way you see fit.
Just join your tables and then count the number of comments for that post.
SELECT p.id, p.title, p.body, COUNT(pc.id) as comments
FROM Post p
LEFT JOIN Comments pc ON (p.id = pc.id_post)
GROUP BY pc.id_post LIMIT 100
Hope that is what you are after.
Join your posts table with your posts-info tables, and select them at the same time
select p.id,pi.comments from posts as p, post_info as pi where p.id == pi.id
or something like that.
EDIT:
select p.title,p.body,p.date,count(c.id) from post as p, comments as c where p.id == c.id_post
I believe.
Beginner here! I am trying to write a query that will select the 3 most commented on results from a "results" table the comments are stored in a seperate "comments" table.
results
- id
- title
- body
- etc
- etc
comments
- id
- result_id
- user_id
- timestamp
- comment
So I need to select all from results and order by the amount of matches between results.id and comments.result_id but I don't really know where to start!
Thanks a lot for the help, it's much appreciated!
Not tested but you can do something like that
SELECT r.id ,r.title, r.body
FROM results r INNER JOIN (SELECT result_id, count(id) cnt FROM comments GROUP BY result_id) c
ON r.id = c.result_id
ORDER by c.cnt DESC
Perhaps try something like this:
SELECT COUNT(c.id) AS comment_count FROM results r
LEFT JOIN comments c ON r.id=c.result_id
GROUP BY result_id ORDER BY comment_count DESC LIMIT 3;
The following should work:
SELECT r.id, COUNT(r.id) AS comment_count
FROM results r
INNER JOIN comments c
ON results.id = c.result_id
GROUP BY r.id
ORDER BY comment_count DESC
You join the two tables where the id of the result is the same as the referenced result_id from the comments table. Then you group the rows by result_id to remove duplicates. The COUNT() function sums up the grouped rows and displays the number of them.
Then just sort the result based on the generated comment count.
You could use LEFT OUTER JOIN as well, then you would get all results that have no comments as well. If you want this or not depends on your needs.
For a description of SQL joins, check out What is the difference between "INNER JOIN" and "OUTER JOIN"?
Basically,
I have two tables, one with Some posts on and another for comments, what I am trying to do is create a page with the most popular posts, I will render popular posts depending on how many comments it has.
Here's the query I have so far
mysql_query("SELECT * FROM posts JOIN comments ON posts.id = comments.content_id ORDER BY count('comments.id') LIMIT 10");
But the count() is messing it up, could anyone help me? THANKS!
If you have an aggregate function, such as COUNT(*), you should include a GROUP BY clause:
Also, since you want to return posts with the most comments, you'll want to sort by the count in descending order (highest to lowest).
SELECT
posts.id,
COUNT(comments.content_id) as post_comments
FROM
posts
LEFT JOIN comments
ON posts.id = comments.content_id
GROUP BY posts.id
ORDER BY post_comments DESC
LIMIT 10
Remove the quotations around comments.id :) I've also added the group by that I believe is missing.
mysql_query("SELECT * FROM posts JOIN comments ON posts.id = comments.content_id GROUP BY posts.id ORDER BY count(comments.id) LIMIT 10");
Remove the quotes from the count statement and add a group by:
SELECT * FROM posts
JOIN comments ON posts.id = comments.content_id
GROUP BY comments.content_id
ORDER BY count(comments.content_id)
LIMIT 10
I have two tables as posts and comments. Each row in comments table has id of the post which it belong to. How can I select, for example, most commented ten posts?
Try this
SELECT p.id, COUNT(c.id) tot
FROM posts p INNER JOIN comments c
ON p.id = c.post_id
GROUP BY p.id
ORDER BY tot DESC
LIMIT 10
you can use group by for this
some query like
SELECT posts, count(comment) as total
from comments group by (post) order by total;