views:

111

answers:

2

I'd like to get in one query a post and the first comment associated with the post. Here is how I do it in PostgreSQL:

SELECT p.post_id, 
(select * from 
 (select comment_body from comments where post_id = p.post_id 
 order by created_date asc) where rownum=1
) the_first_comment
FROM posts p  

and it works fine.

However, in Oracle I'm getting an error ORA-00904 p.post_id: invalid identifier.

It seems to work fine for one subselect, but I cannot get the comment with only one due to the fact that I need to use rownum (no limit / offset in Oracle).

What am I doing wrong here?

+7  A: 

No, Oracle doesn't correlate the subqueries nested more than one level deep (and neither does MySQL).

This is a well-known problem.

Use this:

SELECT  p.post_id, c.*
FROM    posts
JOIN    (
        SELECT  c.*, ROW_NUMBER() OVER (PARTITION BY post_id ORDER BY created_date ASC) AS rn
        FROM    comments c
        ) c
ON      c.post_id = p.post_id
        AND rn = 1
Quassnoi
Thanks Quassnoi, that's of course a good answer (although stupidly complex, but probably PostgreSQL spoiled me a bit). Sorry for not replying earlier but my employer doesn't like me to use StackOverflow blocking the site and using proxy I can only ask questions, not comment (probably an issue with SO ajax code).
+1  A: 

If you need SQL that is platform-independent, this will work:

SELECT p.post_id
     , c.comment_body
  FROM posts p
     , comments c
 WHERE p.post_id = c.post_id
   AND c.created_date IN
       ( SELECT MIN(c2.created_date)
           FROM comments c2
          WHERE c2.post_id = p.post_id
        );

But it assumes that (post_id, created_date) is the primary key of comments. If it isn't, you're going to get more than one line posts that have comments with the same created_date.

Also, it is likely to be slower than the solution that uses analytics, given by Quassnoi.

Steve Broberg
That would be a bit dangerous. Create date cannot be guaranteed to be unique. But just using MIN(comment_id) should be fine as it's taken from the sequence. I used Quassnoi's solution, though.