I have two tables: posts and post_translations. A post can be translated into many languages, and its translations are stored in the post_translations table. Not all posts are available in all languages.
posts:
+----+------+
| id | hits |
+----+------+
| 1 | 12 |
+----+------+
| 2 | 34 |
+-----------+
post_translations:
+----+---------+--------+---------------+------+
| id | post_id | locale | title | body |
+----+---------+--------+---------------+------+
| 1 | 1 | en | Hello, world! | Hey. |
+----+---------+------------------------+------+
| 2 | 1 | es | ¡Hola, mundo! | Olé. |
+----+---------+--------+---------------+------+
| 3 | 2 | en | How are you? | Meh. |
+----+---------+--------+---------------+------+
I’d like to SELECT all posts, ordered by Spanish title—but, since not all posts are available in Spanish, I’d also like to fall back to English title if necessary. That is, ORDER BY title_with_fallbacks where title_with_fallbacks = [spanish title] || [english title].
I suppose I could use a dependent subquery:
SELECT * FROM posts ORDER BY (SELECT name FROM post_translations
WHERE post_id = posts.id
ORDER BY FIELD(locale, 'es', 'en')
LIMIT 1)
But that could get nasty fast if there are thousands of results. Any clever ideas of how to get the same result by joining the two tables or something along those lines?
(For reference, I’m using the Rails plugin globalize3, but I haven’t been able to find any built-in mechanism to get this job done.)
This query accomplishes the conditional ordering with two
left joins… One to the Spanish translation, and another to the English translation…The
ORDER BYthen uses theIFNULLfunction to order by the Spanish title, and if the Spanish title isNULL, order by the English title instead.