views:

376

answers:

2

Hey Stackers,

Since SQLite does not support RIGHT OUTER JOINS I pose the following challenge (read: invitation to do my work for me):

Refactor this query so it no longer utilises SQLite-unsupported constructs like RIGHT/FULL OUTER JOINs.

SELECT     strings.*, translations.text
FROM         translations INNER JOIN
                      language ON translations.language_id = language.id RIGHT OUTER JOIN
                      strings ON translations.string_id = strings.id
WHERE     (language.handle = 'english')

I sense it can be achieved with subqueries or by pivoting the tables and performing a LEFT OUTER JOIN but my attempts have failed; my SQL's not what it used to be.

Here's a query builder outline showing the applicable schema: http://dl.getdropbox.com/u/264612/sql-refactor.PNG

First to crack it gets an e-hug from dekz

+3  A: 

The following is untested.

select strings.*, translations.text
from strings left outer join translations
     on translations.string_id = strings.id
           and translations.language_id = (select id
                                           from language
                                           where language.handle = 'english')

I think this will give you all strings with the matching translation text where a suitable translation exists in English. Is that what you are trying to get?

tvanfosson
Cheers. This worked awesomely although I'm wondering if it can be done without the subquery as in j_random_hacker's method.
The subquery is probably going to be faster than another join in this case, since it will only need to be executed once. If SQLLite is ok with it, I'd keep it.
Blorgbeard
+2  A: 

Intriguing that SQLite allows LEFT OUTER JOINs but not RIGHT OUTER JOINs. Well, since it does allow LEFT OUTER JOINs, you're right, you can just rearrange the join order:

SELECT     strings.*, translations.text
FROM strings LEFT OUTER JOIN (
    translations INNER JOIN language ON translations.language_id = language.id
) tr ON tr.string_id = strings.id
WHERE     (language.handle = 'english')

[EDIT: Applied Blorgbeard's suggestion of naming the joined table to get the query to parse -- hope it works now!]

j_random_hacker
Makes a lot of sense to me :)
Alex
I like that this doesn't use a subquery but I couldn't get it to parse. It was failing around the "ON translations" part...
try changing `) ON translations.string_id = strings.id` to `) tr ON tr.string_id = strings.id` - I'd edit the post, but I'm not 100% sure it will work :P
Blorgbeard
I'm not sure about SQLite's syntax, but Blorgbeard's suggestion above is the way I would try to fix that. You may additionally need the word "AS" between ")" and "tr". If that fixes it, let me know and I'll edit the post (crediting Blorgbeard of course).
j_random_hacker
I've actually gone ahead and made Blorgbeard's change, as I feel it can't be worse than leaving up a query that contains an error... :)
j_random_hacker