Один запрос для нескольких отборов - даже если один выбор возвращает пустой
Мне нужно сделать несколько операторов выбора, чтобы получить простые данные (только одна строка, содержащая одно или несколько полей для каждого выбора).
Упрощенный пример:
select name, price from article where id=125
select log, email from user where uid=241
Я хочу обработать только один оператор со стороны php (или: Я НЕ хочу готовить несколько операторов, выполнять несколько операторов, перехватывать и обрабатывать исключения для каждого выполнения и, наконец, извлекать результат для каждого оператора...).
Я старался:
select * from (
(select name, price from article where id=125) as a,
(select log, email from user where uid=241) as b
)
который прекрасно работает, если каждый подвыбор возвращает значения:
name | price | log | email
------------------------------------------
dummy | 12,04 | john | john@example.com
Но если один из подвыборов возвращается пустым, весь выбор возвращается пустым.
То, что я хочу: нулевые значения для пустых результирующих подвыборов
Я перепробовал много вещей с ifnull()
а также coalesce()
, но не смог получить ожидаемый результат (я знаю, как использовать их с нулевыми значениями, но я не нашел способа справиться с ними в случае пустого набора результатов).
Я наконец нашел решение с левыми соединениями:
select * from (
(select 1) as thisWillNeverReturnEmpty
left join (select name, price from article where id=125) as a on 1
left join (select log, email from user where uid=241) as b on 1
)
который отлично работает, даже если один из подзапросов возвращает пустой (или даже оба, следовательно, "select 1").
Другой способ, который я нашел на SO, - это добавить count(*)
в каждом подзапросе, чтобы убедиться, что есть значение.
Но все выглядит довольно грязно, и я не могу поверить, что нет простого способа использовать что-то вроде ifnull()
, Как правильно это сделать?
1 ответ
Лучший способ, который я наконец нашел, был:
select * from (
(select count(*) as nbArt, name, price from article where id=125) as a,
(select count(*) as nbUser, log, email from user where uid=241) as b
)
Таким образом, ни один подзапрос никогда не возвращает пустое значение, что решает проблему (всегда есть хотя бы "нулевой" счетчик, за которым следуют нулевые значения).
Пример результата, когда статья не найдена:
nbArt | name | price | nbUser | log | email
----------------------------------------------------------------
0 | null | null | 1 | john | john@example.com