I have two tables called 'events' and 'topics' each table can have many comments.
What I need to do is list all the events and topics with the amount of comments for each row. I've managed to return all the topics, which works great but I don't know how I can add the events table to the MySql. The comments and events table fields are listed below. Can anyone help me with this query?
Events:
ID
Event_Name
Comments:
post_id <-- the releated id for either the events or topics table
table <-- The table that the row belongs to so either topics or events
SELECT
t.id, t.title, c.created_at,
IF(ISNULL(c.allComments), 0, c.allComments) AS totalComments
FROM topics AS t
LEFT OUTER JOIN (
SELECT created_at, post_id, COUNT(*) AS allComments
FROM comments
GROUP BY post_id
) AS c ON c.post_id = t.id
ORDER BY tc.created_at DESC, c.allComments DESC
Sounds like events and topics should be the same table.
Still, I think we can do this with a UNION. Events and Topics have the same columns i hope? (Or at least the same important ones?)
(SELECT c.table as event_or_topic, e.*, count(C.table), MAX(C.created_at) as latest_c
FROM events E LEFT JOIN comments C on (C.post_id = E.id)
WHERE C.table = 'Events'
GROUP BY C.post_id)
UNION
(SELECT c.table as event_or_topic, t.id*, count(C.table), MAX(C.created_at) as latest_c
FROM topics T LEFT JOIN comments C on (C.post_id = E.id)
WHERE C.table = 'Topics'
GROUP BY C.post_id)
ORDER BY latest_c
Notice that the ORDER BY applies to the whole UNION, not the individual SELECTs.
The use of LEFT JOIN should allow those rows without Comments to still show. I think the problem is that we have parts of our select dependent on comments (ie - C.table, ordering on last comment, etc). The count should be fine - will just be zero if there are no comments.
You might need to change the SELECT part slightly. I'd like to display C.table so you know whether a row is a topic or event, but im afraid it might screw up the count. Do you need anything from comments besides the count? You use some columns other than post_id and table in your query that you neglected to explain in your question.
You still have columns I don't know what they are, like Comment's zoneTable
Try this:
SELECT
t.id, t.title, c.created_at, COUNT(c.allComments) AS totalComments
FROM topics AS t LEFT JOIN comments c ON t.id=c.post_id
GROUP BY t.id ORDER BY tc.created_at DESC, c.allComments DESC
If I understand your question you have 3 tables:
-Events
-Topics
-Comments
If that is true something like this should extract all the data:
SELECT *
FROM events,topics
LEFT JOIN comments ON post_ID = ID
ORDER BY date DESC
Hope i'm along the right lines!
W.
I've got it working. If anyone knows of a better and an efficient way of doing this, then please let me know:
(SELECT t.id, t.title, tc.dateCreated AS commentDate,
IF(ISNULL(tc.allComments), 0, tc.allComments) AS totalComments,
t.LastActive as dateChanged
FROM Events AS t
LEFT OUTER JOIN (
SELECT MAX(created_at) AS dateCreated, post_id,
COUNT(*) AS allComments
FROM comments
GROUP BY post_id
) AS tc ON tc.post_id = t.id)
UNION
(SELECT t.id, t.title, tc.dateCreated AS commentDate,
IF(ISNULL(tc.allComments), 0, tc.allComments) AS totalComments,
t.LastActive as dateChanged
FROM topics AS t
LEFT OUTER JOIN (
SELECT MAX(created_at) AS dateCreated, post_id,
COUNT(*) AS allComments
FROM comments
GROUP BY post_id
) AS tc ON tc.post_id = t.id)
ORDER BY commentDate DESC, dateChanged DESC, totalComments DESC
Related
I am trying to sort two tables that I created for a forum by timestamp.
I have searched with no luck yet. Please help.
My first table is "forum_posts" and timestamp is "forum_timestamp"
My second table is "forum_posts_replys" is "fpr_timestamp"
With the following query I am able to sort by timestamp or the other, but I would like to sort both. If there are not any replys in a topic yet and it was just posted I would like to see it on the top, but if there is a reply in another topic I would like that reply to show first.
(SELECT fp.*, fpr.*
FROM forum_posts fp
LEFT JOIN forum_posts_replys fpr
ON fp.forum_post_id = fpr.fpr_post_id
WHERE `fp`.`forum_id`='$f_id'
GROUP BY fp.forum_post_id)
ORDER BY `forum_timestamp` DESC
I also tried GREATEST() and no luck.
The page I am trying to use this on is the main topic listing page. The page just shows topics with their titles and a count of replys and how long ago each was posted.
My current query 06/14/14:
SELECT sub.*
FROM
(SELECT
fp.forum_post_id as forum_post_id, fp.forum_id as forum_id,
fp.forum_user_id as forum_user_id, fp.forum_title as forum_title,
fp.forum_content as forum_content, fp.forum_edit_date as forum_edit_date,
fp.forum_timestamp as forum_timestamp, fpr.id as id,
fpr.fpr_post_id as fpr_post_id, fpr.fpr_id as fpr_id,
fpr.fpr_user_id as fpr_user_id, fpr.fpr_title as fpr_title,
fpr.fpr_content as fpr_content, fpr.fpr_edit_date as fpr_edit_date,
fpr.fpr_timestamp as fpr_timestamp,
ifnull(fpr.fpr_timestamp,forum_timestamp) as tstamp
FROM forum_posts fp
LEFT JOIN forum_posts_replys fpr
ON fp.forum_post_id = fpr.fpr_post_id
WHERE `fp`.`forum_id`='$f_id'
GROUP BY fp.forum_post_id) sub
ORDER BY tstamp DESC
Still only seems to sort by forum_timestamp
Use a subquery.
SELECT fp.*, fpr.*
from
(SELECT fp.*, fpr.*, ifnull(fpr.fpr_timestamp,forum_timestamp) as tstamp
FROM forum_posts fp
LEFT JOIN forum_posts_replys fpr
ON fp.forum_post_id = fpr.fpr_post_id
WHERE `fp`.`forum_id`='$f_id'
GROUP BY fp.forum_post_id) sub
order by tstamp desc
Edit: List the wanted fields explicitly and use the table alias for the subquery:
SELECT sub.*
from
(SELECT fp.field_1 as f1, fp.field_2 as f2, fpr.field_1 as f3, fpr.field_2 as f4, ifnull(fpr.fpr_timestamp,forum_timestamp) as tstamp
FROM forum_posts fp
LEFT JOIN forum_posts_replys fpr
ON fp.forum_post_id = fpr.fpr_post_id
WHERE `fp`.`forum_id`='$f_id'
GROUP BY fp.forum_post_id) sub
order by tstamp desc
With your help I was able to troubleshoot this to make it work!
Here is the final query that worked flawlessly.
SELECT sub.*
FROM
(SELECT
fp.forum_post_id as forum_post_id, fp.forum_id as forum_id,
fp.forum_user_id as forum_user_id, fp.forum_title as forum_title,
fp.forum_content as forum_content, fp.forum_edit_date as forum_edit_date,
fp.forum_timestamp as forum_timestamp, fpr.id as id,
fpr.fpr_post_id as fpr_post_id, fpr.fpr_id as fpr_id,
fpr.fpr_user_id as fpr_user_id, fpr.fpr_title as fpr_title,
fpr.fpr_content as fpr_content, fpr.fpr_edit_date as fpr_edit_date,
fpr.fpr_timestamp as fpr_timestamp,
GREATEST(fp.forum_timestamp, COALESCE(fpr.fpr_timestamp, '00-00-00 00:00:00')) AS tstamp
FROM forum_posts fp
LEFT JOIN forum_posts_replys fpr
ON fp.forum_post_id = fpr.fpr_post_id
WHERE fp.forum_id=$f_id
ORDER BY tstamp DESC
) sub
GROUP BY forum_post_id
ORDER BY tstamp DESC
I am having trouble with this query and am hoping someone can help.
SELECT
myTable.id,
myTable.subject,
myTable.upvotes,
myTable.downvotes,
(SELECT COUNT(id)
FROM myTable
WHERE myTable.thread = myTable.id) AS comments_count
FROM myTable
Basically I have a table with posts and comments, the comments thread is tied to the id of the original post. In my query I want to show how many relpies (how many threads = id) from all rows for the current id/row.
I hope that makes sense :)
You need to specify the the table with new alias to match in your subquery other wise it will match the thread with id from same table
SELECT
m.id,
m.subject,
m.upvotes,
m.downvotes,
(SELECT COUNT(id)
FROM myTable
WHERE myTable.thread = m.id) AS comments_count
FROM myTable m
Or Better to use LEFT JOIN
SELECT
m.id,
m.subject,
m.upvotes,
m.downvotes,
COUNT(mm.id) AS comments_count
FROM myTable m
LEFT JOIN myTable mm ON(mm.thread = m.id)
GROUP BY m.id
I have two tables :
posts : id,title,content,show,created_at
comments: id,post_id,created_at
I'm trying to order posts by most commented.
SELECT *, COUNT(comments.id) AS total_comments
FROM comments LEFT JOIN posts ON posts.id = comments.post_id
WHERE posts.show = '1'
GROUP BY complains.id
ORDER BY total_comments DESC
The problem is that the posts with 0 comments don't appear.
Any help would be much appreciated.
With your join above, you are incorrectly joining to get commens that have posts
You should have done a right join or swap the tables in left join like below.
Select *, COUNT(comments.id) as total_comments
FROM posts
LEFT outer JOIN comments on posts.id = comments.post_id
WHERE posts.show = '1'
GROUP BY posts.id
ORDER BY total_comments DESC
You need to do a RIGHT JOIN instead of a LEFT JOIN. Or swap the tables in the LEFT JOIN clause.
While there are many ways to solve this, I think this code is easy to read and understand.
The query in the LEFT JOIN can be copied out and run on its own to help debug. Then you join that result set to the posts table and order the results.
SELECT p.*, IFNULL(c.total_comments, 0) as total_comments
FROM posts p
LEFT JOIN (select post_id, count(post_id) as total_comments from comments group by post_id) as c ON p.id = c.post_id
WHERE p.show = '1'
ORDER BY c.total_comments DESC
I'm trying to get PHP to list out comments by descending number of likes they receive.
Currently, the comments' content and the number of likes they receive are in 2 separate tables: "comments" and "likes".
PHP code:
To get comments from "comments" table:
$this->db->order_by ('comment_id', 'asc');
$data['comment'] = $this->db->select()->get('comment');
To get likes from "likes" table:
$data['like'] = $this->db->get('like');
To show the number of likes for each comment:
$query_like=$this->db->query("select ip from like where comment_id='$comment_id'");
$count_like=$query_like->num_rows();
I'm wondering if it's possible to order the comments by the number of likes they receive without changing the tables' structure. Any advice hugely appreciated.
If I understand the data structure correctly, you just need a join and an aggregation:
select c.*, count(*) as numlikes
from comments c join
upvote l
on c.comment_id = l.comment_id
group by c.comment_id
order by count(*) desc;
EDIT:
To get comments with zero upvotes, do the left outer join in the other direction:
SELECT c.*, count(u.comment_id) as num_upvotes
FROM comment c left join
upvote u
on c.comment_id = u.comment_id
WHERE c.comment_id = '$interview_id'
GROUP BY c.comment_id
ORDER BY num_upvotes DESC;
I have this diagram
What I wanna do is have this output:
How do you manage to do the query of this one?
I have this code
SELECT users.firstname, users.lastname,
users.screenname, posts.post_id, posts.user_id,
posts.post, posts.upload_name,
posts.post_type, posts.date_posted
FROM website.users users
INNER JOIN website.posts posts ON (users.user_id = posts.user_id)
ORDER BY posts.pid DESC
//PROBLEM with this one is that it only views the post from all users.
//SO I added
SELECT COUNT(user_id) AS friends, SUM(user_id = ?) AS you, user_id
FROM feeds WHERE post_id = ?
//This one will give you two fields containing how many different users **feeds** the
post
Please help guys. Actually this one I am just following Facebook's "LIKE" status
the only thing is I'm not an amateur with this kind of stuff so I'd be glad to hear all your answers. I really need your help
If I've understood you correctly, you want an outer join with the feeds table (in order to retain all posts even if there are no associated feeds), then GROUP BY post.pid in order to amalgamate together all such feeds for each post, and SELECT the desired information.
I use MySQL's GROUP_CONCAT() function to obtain a comma-separated list of all users (up to group_concat_max_len) who have
a "feed" for the given post (you can change the delimiter with the SEPARATOR modifier, if so desired).
SELECT users.firstname, users.lastname,
users.screenname, posts.post_id, posts.user_id,
posts.post, posts.upload_name,
posts.post_type, posts.date_posted,
COUNT(feeds.user_id) AS friends, -- number of "likes"
SUM(feeds.user_id = ?) AS you, -- did I like this?
GROUP_CONCAT(feeds.user_id) -- who likes it?
FROM website.users users
INNER JOIN website.posts posts ON (users.user_id = posts.user_id)
LEFT JOIN website.feeds feeds ON (posts.post_id = feeds.post_id)
GROUP BY posts.pid
ORDER BY posts.pid DESC
UPDATE
To obtain the full name of users who have "liked" the post, excluding oneself, one needs to join the users table a second time:
SELECT users.firstname, users.lastname,
users.screenname, posts.post_id, posts.user_id,
posts.post, posts.upload_name,
posts.post_type, posts.date_posted,
COUNT(feeds.user_id) AS friends, -- number of "likes"
SUM(feeds.user_id = ?) AS you, -- did I like this?
GROUP_CONCAT(
CASE WHEN NOT likes.user_id = ? THEN -- exclude self
CONCAT_WS(' ', likes.firstname, likes.lastname) -- full names
END
)
FROM website.users users
INNER JOIN website.posts posts ON (users.user_id = posts.user_id)
LEFT JOIN website.feeds feeds ON (posts.post_id = feeds.post_id)
LEFT JOIN website.users likes ON (feeds.user_id = likes.user_id)
GROUP BY posts.pid
ORDER BY posts.pid DESC
If You want to do it for all the users and simultaneously get the feeds, You have to join this feed table:
SELECT u.firstname, u.lastname,
u.screenname, p.post_id, p.user_id,
p.post, p.upload_name,
p.post_type, p.date_posted,
COUNT(f.user_id) AS friends, SUM(f.user_id = ?) AS you
FROM website.users u
INNER JOIN website.posts p ON (u.user_id = p.user_id)
LEFT JOIN website.feeds f ON (p.post_id = f.post_id)
GROUP BY p.pid
ORDER BY p.pid DESC
This one should do the trick...