views:

72

answers:

1

Suppose I have two tables, one with blog posts and another with readers and their comments:

Table 1:

table name: BlogPosts:

structure:

id (int)

title (string)

Table 2:

table name: Readers:

id (int)

blog_post_id (int)
name (string)
comment (string)

in the Readers table there is a unique composite key on blog_post_id/name (i.e. one comment per reader per post), though this may not matter for my question.

I want to be able to do a single query tells me what a particular reader's comment was on each BlogPost, but it should include BlogPosts for which there is no comment entered for that reader (so the query should return one row for each blog post in the database).

I tried several variations that look like this:

SELECT  
     BlogPosts.id,
     BlogPosts.title,
     Readers.name,
     Readers.comment
    FROM
         BlogPosts
    RIGHT JOIN Readers ON
    (BlogPosts.id = Readers.blog_post_id)
    WHERE Readers.name = "joe"

..this just returns the rows where there is actually a comment from joe. Other variations where I was able to get all of the blog posts gave me an invalid identifier whenever I included the where clause.

I am using Oracle Express 10g in case that makes any difference.

Thanks for any help.

+4  A: 

Everything looks correct except that you want to move the WHERE clause into the join, like this:

    SELECT BlogPosts.id,
           BlogPosts.title,
           Readers.name,
           Readers.comment
      FROM BlogPosts
RIGHT JOIN Readers ON BlogPosts.id = Readers.blog_post_id
       AND Readers.name = 'joe'

You effectively make the OUTER JOIN into an INNER one when you put the Readers.name = 'joe' in the WHERE clause.

Edit:
Thanks to the OP for clarification in the comments.
What you describe in your most recent comment can be achieved simply by switching from a RIGHT JOIN to a LEFT JOIN (as suggested earlier on by another commenter).
Note that you can get more than one row per BlogPost when there are multiple comments per post.

Adam Bernier
That will work, but you may want to consider changing RIGHT JOIN to a LEFT OUTER JOIN. For whatever reason, LEFT is much more popular than RIGHT, at least with every system and developer I've worked with (but I'd be interested to hear if other people have different experiences). I know it's just a style thing that doesn't really matter for this particular query, but it's probably a good habit to get into.
jonearles
That is one of the variations I had tried. I get: ORA-00904: "joe": invalid identifier
Ken Thompson
Use single-quotes instead. I edited my answer.
Adam Bernier
Hmm...changing to single quotes made the query work it didn't return what was expected. Here is the exact query pasted right from the command prompt:SELECT BlogPosts.id, BlogPosts.title, Readers.name, Readers.comment_text FROM BlogPostsRIGHT JOIN Readers ON BlogPosts.id = Readers.blog_post_id AND Readers.name = 'joe'
Ken Thompson
Two of the returned rows have null values in the id and title fields.
Ken Thompson
Sorry this is hard to read but I'm not very good with this code "editor"
Ken Thompson
Anyway, this query is returning a number of rows equal to the number of rows in the Readers table.
Ken Thompson
I finally got it working. The query as written in my previous comment works IF you change the "RIGHT JOIN" to "LEFT OUTER JOIN". I'm a bit new here so not sure of the proper protocol..should I leave this here in the comment or edit my original question? Thank
Ken Thompson
Sorry I hadn't seen your edit Adam when I posted my last comment. The main stumbling block when I was originally trying several variations was actually the single vs double quotes so thanks for your help especially on that point. I have been using ORM tools too much and the real drawback is they get you out of practice writing queries.
Ken Thompson