Question

I have a SQL statement that I'm trying to run, but it's throwing an error:

SELECT fp.forum_id, COUNT(fp.forum_id) AS num_posts
FROM forums_posts fp
GROUP BY fp.forum_id
WHERE (
    SELECT COUNT(p.post_id) AS num_joined_posts
    FROM posts p
    WHERE p.post_type IN ('TypeA', 'TypeB', 'TypeC')
        AND p.forum_id = fp.forum_id
) > 0
ORDER BY num_posts DESC

The forums_posts table is a relational table matching forum IDs to post IDs, and the posts table (which also stores the post's forum ID) just contains info about each post. I am trying to find out: which forums have posts of the type TypeA, TypeB, or TypeC; and how many posts are in each of those forums.

Nested SQL statements have never been my strong suit. Can somebody point out the correct way to go about doing this? Thanks.

Was it helpful?

Solution

The where should be before the group by.

You can also write this using an explicit join:

SELECT fp.forum_id, COUNT(fp.forum_id) AS num_posts
FROM forums_posts fp join
     (SELECT p.forum_id, COUNT(p.post_id) AS num_joined_posts
      FROM posts p
      WHERE p.post_type IN ('TypeA', 'TypeB', 'TypeC')
      group by p.forum_id
     ) p
     on p.forum_id = fp.forum_id
GROUP BY fp.forum_id
ORDER BY num_posts DESC

Although, I'm thinking the most efficient rendition might be:

SELECT fp.forum_id, COUNT(fp.forum_id) AS num_posts
FROM forums_posts fp join
GROUP BY fp.forum_id
having exists (select 1
               FROM posts p
               WHERE p.post_type IN ('TypeA', 'TypeB', 'TypeC') and
                     p.forum_id = pf.forum_id
               limit 1
              )
ORDER BY num_posts DESC

Particularly if you have an index on posts(forum_id, post_type). I move the condition to the having clause from a where clause because there is presumably less data for this comparison after the grouping.

OTHER TIPS

Try this-

SELECT fp.forum_id, COUNT(fp.forum_id) AS num_posts
FROM forums_posts fp
WHERE (
    SELECT COUNT(p.post_id) AS num_joined_posts
    FROM posts p
    WHERE p.post_type IN ('TypeA', 'TypeB', 'TypeC')
        AND p.forum_id = fp.forum_id
) > 0
GROUP BY fp.forum_id
ORDER BY num_posts DESC

This is how I would do it, SQL tends to be faster using a join.

SELECT * FROM 
(
  SELECT fp.forum_id,
       SUM(CASE p.post_type = 'TypeA' THEN 1 ELSE 0 END) AS A_Count,
       SUM(CASE p.post_type = 'TypeB' THEN 1 ELSE 0 END) AS B_Count,
       SUM(CASE p.post_type = 'TypeC' THEN 1 ELSE 0 END) AS C_Count
  FROM forums_posts fp
  LEFT JOIN posts p ON fp.forum_id = p.forum_id
  GROUP BY fp.forum_id
) T
WHERE T.A_count > 0 AND T.B_count > 0 AND T.C_count > 0 

I have not tested this so it might have typos.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top