I have many tables, but the only one interesting here is the following, let’s call it webpages
| companyID | lang | URL
| 1 | hu | hu.example.com/x
| 1 | en | en.example.com/x
| 1 | NULL | www.example.com/x
| 1 | NULL | www.example.com/x2
| 3 | NULL | www.example.com/y
| 4 | en | en.example.com/z
My SQL is something like this
SELECT `companies`.*, `webpages`.`lang`, `webpages`.`URL`
FROM `companies` LEFT JOIN `webpages`
ON `companies`.`companyID` = `webpages`.`companyID`
AND (`webpages`.`lang` = :lang OR `webpages`.`lang` IS NULL)
For example for lang = 'hu'
I got this:
| companyID | lang | URL
| 1 | hu | hu.example.com/x
| 1 | NULL | www.example.com/x
| 1 | NULL | www.example.com/x2
| 2 | NULL | NULL
| 3 | NULL | www.example.com/y
| 4 | NULL | NULL
I’d like to achieve the following for lang = 'hu'
:
| companyID | lang | URL
| 1 | hu | hu.example.com/x
| 2 | NULL | NULL
| 3 | NULL | www.example.com/y
| 4 | NULL | NULL
And for lang = 'de'
:
| companyID | lang | URL
| 1 | NULL | www.example.com/x2
| 2 | NULL | NULL
| 3 | NULL | www.example.com/y
| 4 | NULL | NULL
And for lang = 'en'
:
| companyID | lang | URL
| 1 | en | en.example.com/x
| 2 | NULL | NULL
| 3 | NULL | www.example.com/y
| 4 | en | en.example.com/z
So lang = NULL
is a fallback for the language specific URL and a single company can have multiple fallback URLs. If there is no language specific URL given, then either a fallback URL should be chosen or if there is no fallback URL then the value should be NULL.
I am not sure if this is possible with a single SQL, currently I use PHP code to achieve the same thing, but it would be fun to have an SQL for this. Any advice how to do this?
2
Answers
You want to select the line with the language code (when found), and otherwise the line with language code is null?
The
MIN()
is needed to make clear which value to return for a company, when multiple values are found. I choose MIN() to get the lowest (or first) value, I also could have chosen MAX() to get the highest (or last) value.see: DBFIDDLE
ORDER BY CASE
in subquery creates priority.p=1
in outer query filters by unwanted languagesOutput:
fiddle