Find total user posting per post SQL QUERY - sql

I have a Database with the following two tables, member, POSTS I am looking for a way to get the count of how many posts a user has.
(Source: http://i.stack.imgur.com/FDv31.png)
I have tried many variations of the following SQL command with out any success. instead of showing the count of posts for a single user it shows a single row with all the posts as the count.
In the end I want something like this
(Source: http://i.stack.imgur.com/EbaEj.png)

Might be that I'm missing something here, but this query would seem to give you the results you want:
SELECT member.ID,
member.Name,
(SELECT COUNT(*) FROM Posts WHERE member.ID = Posts.user_id) AS total
FROM member;
I have left comment out of the query as it is not obvious what comment you want to be returned in that column for the group of comments that is counted.
See a SQL Fiddle demo here.
Edit
Sorry, misinterpreted your question :-) This query will properly return all the comments, along with the person who posted them and the total number of comments that the person made:
SELECT Posts.ID,
member.Name,
(SELECT COUNT(*) FROM Posts WHERE member.ID = Posts.user_id) AS total,
Posts.comment
FROM Posts
INNER JOIN member ON Posts.user_id = member.ID
GROUP BY Posts.ID, member.Name, member.ID, Posts.comment;
See an updated SQL Fiddle demo here.

You could use a subquery to calculate the total posts per member:
select m.ID
, m.Name
, coalesce(grp.total, 0)
, p.comment
from member m
left join
posts p
on p.user_id = m.id
left join
(
select user_id
, count(*) as total
from posts
group by
user_id
) grp
on grp.user_id = m.id

select
a.id
, a.name
, count(1) over (partition by b.user_id) as TotalCountPerUser
, b.comment
from member a join post b
on a.id = b.user_id

Related

Group by on join and calculate max of groups

I have 3 tables as described below:
All three tables and output image
posts post table
post_comments posts comments
comments comments
Now I want to fetch the posts that have highest liked comments and the status of that comment should be active in Postgres.
OUTPUT:
posts resultant posts
NOTE: Since for post 1, the highest liked comment is inactive.
I've tried something like this:
select "posts".*
from "posts"
inner join (select id, max(likes) l from comments innner join post_comments on comments.id = post_comments.alert_id and post_comments.post_id = posts.id) a on posts.id = a.cid ...
This is not complete but I'm unable to do this.
In Postgres, you can get the active comment with the most likes for each post using distinct on:
select distinct on (pc.post_id) pc.*
from post_comments pc join
comments c
on pc.comment_id = c.id
where c.status = 'active'
order by pc.post_id, c.likes desc;
I think this is quite related to what you want.
Try something like this:
SELECT posts.*, MAX(likes) l
FROM posts
JOIN post_comments ON post_id = posts.id
LEFT JOIN comments ON comment_id = comments.id
GROUP BY posts.id

how to count two values from three dataset

I have 3 datasets: company, post, postedited,
I want to count the numbers of companies' post and postedited. some companies post but did not edited.
here is my query :
SELECT company.name, company.id, count(*),
( select count(*)
from post, postedited
where post.id=postedited.post_id)
from company, post as p
where company.id=p.company_id
group by company_id
the outcome of post is right, but the column of postedited is the same. what's wrong with my query?
Your subquery is completely unrelated to the main query. It selects post and postedited and counts. You are showing this result for every row of the main query.
You want the subquery relate to the main query's post. So remove the post table from the subquery's from clause:
(select count(*) from postedited where postedited.post_id = p.id)
Now this subquery selects a count for the post_id of the main query's records. At last you must get the sum of the counts:
select
c.name, c.id, count(*) as posts,
sum(select count(*) from postedited pe where pe.post_id = p.id) as edits
from company c
join post p on p.company_id = c.id
group by c.id;
You can achieve the same thus:
select
c.name, c.id, count(distinct p.id) as posts, count(pe.post_id) as edits
from company c
join post p on p.company_id = c.id
left join postedited pe on pe.post_id = p.id
group by c.id;
SELECT c.name AS companyName
, c.id AS companyID
, COUNT(DISTINCT p.id) AS postCount
, COUNT(DISTINCT pe.post_id) AS postEditCount
FROM company c
LEFT OUTER JOIN post p ON p.Company_ID = c.ID
LEFT OUTER JOIN postEdited pe ON pe.Company_ID = c.ID
GROUP BY c.id, c.name
That will give you a list of all companies in your company table with a count of each of their posts and edited posts. If you need to further query against that dataset, you can. Or you can add a WHERE clause to the above query to filter it.
And I agree, please don't use comma syntax. It's very easy to produce unintended results, and it doesn't give a good representation of what you're actually querying against. Plus, it's no longer standard and being deprecated in many flavors of SQL. Good JOIN syntax will make your life much easier.

How to get counts from various joins to the same table in SQL?

I have two tables, blogs and posts, with the expected relationship between them. Posts can be published or draft. I want to select all blogs with the counts of published and draft posts. How can I do it?
I tried this query:
SELECT blogs.*,
COUNT(published_posts.*) AS published_post_count,
COUNT(draft_posts.*) AS draft_post_count
FROM blogs
JOIN posts AS published_posts ON published_posts.blog_id=blogs.id AND
published_posts.state = "published"
JOIN posts AS draft_posts ON draft_posts.blog_id=blogs.id AND
draft_posts.state = "draft"
GROUP BY blogs.id
but I end up with the same number for both published_post_count and draft_post_count and being wrong for both.
Then I got desperate and trie:
SELECT blogs.*,
COUNT(published_posts.*) AS published_post_count,
COUNT(draft_posts.*) AS draft_post_count
FROM blogs
JOIN (SELECT * FROM posts WHERE posts.state="published") AS published_posts
ON published_posts.blog_id=blogs.id
JOIN (SELECT * FROM posts WHERE posts.state="draft") AS draft_posts
ON draft_posts.blog_id=blogs.id
GROUP BY blogs.id
but in both cases I had the same wrong results.
What's the proper way to do this?
Thanks.
If you are just interested in the COUNT and you are also JOINing the tables. So there has to be one or more post that has been published and one or more that is draft. So maybe this will help you:
SELECT blogs.*,
(
SELECT COUNT(*)
FROM posts
WHERE posts.blog_id=blogs.id
AND posts.state = "published"
) AS published_post_count,
(
SELECT COUNT(*)
FROM posts
WHERE posts.blog_id=blogs.id
AND posts.state = "draft"
) AS draft_post_count,
FROM blogs
You might count different states and join back to blogs:
SELECT blogs.*, p.published_post_count, p.draft_post_count
FROM blogs
JOIN
(
SELECT posts.blog_id,
SUM(case when posts.state = 'published' then 1 end)
AS published_post_count,
SUM(case when posts.state = 'draft' then 1 end)
AS draft_post_count
FROM posts
GROUP BY blog_id
) p
ON p.blog_id=blogs.id
Try :
GROUP BY blogs.id,published_posts.[theKeyOfThisTable],draft_posts.[theKeyOfThisTable]
as you should contain the columns of the "select" at your "group by" clause

MySQL COUNT can't count

Well, it can, but I can't query ;)
Here's my query:
SELECT code.id AS codeid, code.title AS codetitle, code.summary AS codesummary, code.author AS codeauthor, code.date, code.challengeid, ratingItems.*, FORMAT((ratingItems.totalPoints / ratingItems.totalVotes), 1) AS rating, code_tags.*, tags.*, users.firstname AS authorname, users.id AS authorid, GROUP_CONCAT(tags.tag SEPARATOR ', ') AS taggroup,
COUNT(DISTINCT comments.codeid) AS commentcount
FROM (code)
JOIN code_tags ON code_tags.code_id = code.id
JOIN tags ON tags.id = code_tags.tag_id
JOIN users ON users.id = code.author
LEFT JOIN comments ON comments.codeid = code.id
LEFT JOIN ratingItems ON uniqueName = code.id
WHERE `code`.`approved` = 1
GROUP BY code_id
ORDER BY date desc
LIMIT 15
The important line is the second one - the one I've indented. I'm asking it to COUNT the number of comments on a particular post, but it doesn't return the right number. For example, something with two comments will return "1". Something with 8 comments by two different authors will still return "1"...
Any ideas?
Thanks!
Jack
EDIT: Forgot to mention. When I remove the DISTINCT part, something with 8 comments from two authors returns "28". Sorry, I'm not a MySQL expert and don't really understand why it's returning that :(
You group by code.id and in each group you count (DISTINCT comments.codeid), but comments.codeid = code.id as defined in JOIN, that's why you always get 1.
You need to count by some other field on comments... if there is a primary surrogate key, this is the way to go COUNT(comments.commentid).
Also, if the comments in every group are known to be distinct, a simple COUNT(*) should work.

SQL: Get all posts with any comments

I need to construct some rather simple SQL, I suppose, but as it's a rare event that I work with DBs these days I can't figure out the details.
I have a table 'posts' with the following columns:
id, caption, text
and a table 'comments' with the following columns:
id, name, text, post_id
What would the (single) SQL statement look like which retrieves the captions of all posts which have one or more comments associated with it through the 'post_id' key? The DBMS is MySQL if it has any relevance for the SQL query.
select p.caption, count(c.id)
from posts p join comments c on p.id = c.post_id
group by p.caption
having count (c.id) > 0
SELECT DISTINCT p.caption, p.id
FROM posts p,
comments c
WHERE c.post_ID = p.ID
I think using a join would be a lot faster than using the IN clause or a subquery.
SELECT DISTINCT caption
FROM posts
INNER JOIN comments ON posts.id = comments.post_id
Forget about counts and subqueries.
The inner join will pick up all the comments that have valid posts and exclude all the posts that have 0 comments. The DISTINCT will coalesce the duplicate caption entries for posts that have more then 1 comment.
I find this syntax to be the most readable in this situation:
SELECT * FROM posts P
WHERE EXISTS (SELECT * FROM Comments WHERE post_id = P.id)
It expresses your intent better than most of the others in this thread - "give me all the posts ..." (select * from posts) "... that have any comments" (where exist (select * from comments ... )). It's essentially the same as the joins above, but because you're not actually doing a join, you don't have to worry about getting duplicates of the records in Posts, so you'll just get one record per post.
SELECT caption FROM posts
INNER JOIN comments ON comments.post_id = posts.id
GROUP BY posts.id;
No need for a having clause or count().
edit: Should be a inner join of course (to avoid nulls if a comment is orphaned), thanks to jishi.
Just going off the top of my head here but maybe something like:
SELECT caption FROM posts WHERE id IN (SELECT post_id FROM comments HAVING count(*) > 0)
You're basically looking at performing a subquery --
SELECT p.caption FROM posts p WHERE (SELECT COUNT(*) FROM comments c WHERE c.post_id=p.id) > 1;
This has the effect of running the SELECT COUNT(*) subquery for each row in the posts table. Depending on the size of your tables, you might consider adding an additional column, comment_count, into your posts table to store the number of corresponding comments, such that you can simply do
SELECT p.caption FROM posts p WHERE comment_count > 1