MySQL, запрос, группировка, агрегатные функции

VHS
На сайте с 28.09.2007
Offline
142
VHS
557

Привет. Есть некая задача, решения по которой как-то не гуглится (не исключаю, что ответ есть). Возможно кто-то сталкивался уже. Нужно найти минимальные значения в таблицах, которые присоединяются слева по условию. Проблема в том, что по условию может придти NULL, что приводит к неверной выборке.

Пример запроса:


SELECT col.id as col_id, col.name as col_name, lower(col.url) as col_url, col.baze as col_baze, col.country as col_country,
col.producer as col_producer, col.type as col_type, col.images as col_images, col.descr as col_descr, col.minD as col_minD,
col.maxD as col_maxD, type.name as type_name, lower(type.url) as type_url, prod.name as prod_name, lower(prod.url) as prod_url,
country.name as country_name, lower(country.url) as country_url, base.name as base_name,
lower(base.url) as base_url, COUNT(unit.id) as count_unit, Count(upricem.id), Count(uprices.id),
MIN(IFNULL(upricem.price,0)) as minpricem, MIN(IFNULL(uprices.price,0)) as minprices

FROM _forum_collections as col
LEFT JOIN _forum_type as type on (col.type = type.id)
LEFT JOIN _forum_producer as prod on (col.producer = prod.id)
LEFT JOIN _forum_country as country on (col.country = country.id)
LEFT JOIN _forum_base as base on (col.baze = base.id)
LEFT JOIN _forum_units as unit on (col.id = unit.col)
LEFT JOIN _forum_units as upricem ON ( col.id = upricem.col )
LEFT JOIN _forum_units as uprices ON ( col.id = uprices.col )

WHERE col.id = '1'
AND upricem.unit = 'м2'
AND uprices.unit = 'шт'

GROUP BY col.id , col.name, col.url, col.baze, col.country,
col.producer, col.type, col.images, col.descr, col.minD,
col.maxD, type.name , type.url , prod.name, prod.url,
country.name , country.url, base.name, base.url

ORDER BY col.name

Кратко - выбирается коллекция, к ней подтягиваются всякие свойства и агрегатными функциями вычисляется количество товаров в коллекции, минимальная цена товаров продаваемых на метраж и минимальная цена товаров продаваемых поштучно для каждой коллекции. Если в коллекции есть и те и те товары - все ок. Как только есть только товары на метраж или только товары поштучно - выборка рушится. В идеале - если нет товаров - возвращать 0.

Вариант с IFNULL не канает...

ДП
На сайте с 23.11.2009
Offline
203
#1

Насколько я понял ваш вопрос - то вот есть такие варианты: http://toster.ru/q/437

Правда там про null нет, вроде.

VHS
На сайте с 28.09.2007
Offline
142
VHS
#2
Дикий пионер:
Насколько я понял ваш вопрос - то вот есть такие варианты: http://toster.ru/q/437
Правда там про null нет, вроде.

нет, не про это. Агрегатные функции игнорируют NULL, а очень хочется, чтобы при LEFT JOIN NULL превращался в 0.

Запрос достаточно активно используемый, поэтому хочется выйти из ситуации с максимально легким для сервера решением.

Joker-jar
На сайте с 26.08.2010
Offline
154
#3

Не совсем понял суть, но может поможет функция Coalesce() ?

VHS
На сайте с 28.09.2007
Offline
142
VHS
#4

Да, суть видимо в запарке. Верным решением было добавлять условия в LEFT JOIN ... ON, а не органичивать выборку в последующем WHERE по всей выборке. Т.е. верный вариант будет таким


SELECT col.id as col_id, col.name as col_name, lower(col.url) as col_url, col.baze as col_baze, col.country as col_country,
col.producer as col_producer, col.type as col_type, col.images as col_images, col.descr as col_descr, col.minD as col_minD,
col.maxD as col_maxD, type.name as type_name, lower(type.url) as type_url, prod.name as prod_name, lower(prod.url) as prod_url,
country.name as country_name, lower(country.url) as country_url, base.name as base_name,
lower(base.url) as base_url, COUNT(unit.id) as count_unit, Count(upricem.id), Count(uprices.id),
MIN(Coalesce(upricem.price,0)) as minpricem, MIN(Coalesce(uprices.price,0)) as minprices

FROM _forum_collections as col
LEFT JOIN _forum_type as type on (col.type = type.id)
LEFT JOIN _forum_producer as prod on (col.producer = prod.id)
LEFT JOIN _forum_country as country on (col.country = country.id)
LEFT JOIN _forum_base as base on (col.baze = base.id)
LEFT JOIN _forum_units as unit on (col.id = unit.col)
LEFT JOIN _forum_units as upricem ON ( col.id = upricem.col AND upricem.unit = 'м2')
LEFT JOIN _forum_units as uprices ON ( col.id = uprices.col AND uprices.unit = 'шт')

WHERE col.id = '1'



GROUP BY col.id , col.name, col.url, col.baze, col.country,
col.producer, col.type, col.images, col.descr, col.minD,
col.maxD, type.name , type.url , prod.name, prod.url,
country.name , country.url, base.name, base.url

ORDER BY col.name

Спасибо всем ответившим!

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий