sql группировка с условиями

http://sqlfiddle.com/#!9/aef5ce/7

В примере выполняются 2 запроса к таблице. Запросы одинаковые, разница только в значении format_id в условии.

В первом ищем format_id = 999 (которого нет в таблице) или NULL, во втором ищем format = 1 (который есть в таблице) или NULL.

Каким образом можно преобразовать эти запросы так, чтобы если мы задаем существующий format_id в таблицах, возвращались только строки с ним (NULL игнорировался). А если такой не существует, то соответственно тянулись те данные, в которых format_id = NULL.

В общем хочется чтобы при заданном format_id = 1 вернулось (3 строки, вместо 6 строк)

100 1 20
200 1 40
300 1 60

При заданном format_id = 999 (или любое другое несуществующее значение) вернулся тот результат, который сейчас отображается в примере в результате 1-го запроса (то есть значение для строки с format_id = null).


Ответы (2 шт):

Автор решения: Mike
SELECT circulation,
       max(format_id) format_id,
       coalesce( min( if(format_id is not null, price1, null) ), min(price1) ) price1
FROM table1
WHERE section_id = 1 AND (format_id = 2 OR format_id IS NULL)
GROUP BY circulation, format_id
order by circulation ASC;

Тест на sqlfiddle.com

→ Ссылка
Автор решения: Akina
SELECT circulation, format_id, min(price1)
FROM table1
WHERE section_id = 1 
  AND CASE WHEN  0 = ( SELECT COUNT(*) 
                       FROM table1
                       WHERE format_id = @format_id )
           THEN format_id IS NULL
           ELSE format_id = @format_id
           END
GROUP BY circulation, format_id
order by circulation ASC, format_id DESC;

fiddle


Подобный подзапрос внутри не будет ли вызывать излишнюю загрузку? Собственно в этом и была вся проблема. Был в поисках адекватного решения, которое минимизирует нагрузку. Поэтому думал, что можно такое как-то провернуть с помощью 1 запроса. Но видимо нельзя?

На 5.6-то? Ну разве что вот так:

SELECT circulation, format_id, min(price1)
FROM table1, ( SELECT COUNT(*) cnt
               FROM table1
               WHERE format_id = @format_id ) sq
WHERE section_id = 1 
  AND CASE WHEN  sq.cnt
           THEN format_id = @format_id
           ELSE format_id IS NULL
           END
GROUP BY circulation, format_id
order by circulation ASC, format_id DESC;

fiddle

Хотя вряд ли будет какая разница...

А без подзапроса - ну никак.

→ Ссылка