Вопрос:
У меня есть следующая проблема: я вычисляю средневзвешенное значение в SQL, как SUM(Value * Weight)/SUM(Weight) ниже: SUM(Value * Weight)/SUM(Weight). Однако может быть проблема, что строки пустые => SUM(Weight) == 0), и в этом случае запрос завершается с ошибкой. Как-то возможно вернуть “0” в результате?
Я попробовал CASE SUM(Weight) WHEN 0 THEN 0 ELSE SUM(Value * Weight)/SUM(Weight) END, но я боюсь, что он дважды оценивает SUM(Weight), и это может быть довольно дорого в моем случае.
Лучший ответ:
Используйте NULLIF и ISNULL:
ISNULL(SUM(Value * Weight) / NULLIF(SUM(Weight),0),0) Ответ №1
Механизм SQL не вычисляет sum(Weight) дважды, только один раз. Концептуальный процесс:
- вычислить полное декартовое объединение всех таблиц в предложении from
- применить критерии соединения для фильтрации результатов
- примените критерии where, чтобы отфильтровать результаты
- разделите этот результирующий набор на группы, как определено в group by предложению
- сворачивать каждую такую группу в одну строку, вычисляя любые агрегированные функции, которые были указаны, сохраняя только те столбцы, которые перечислены в результирующем наборе (функции агрегации и столбцы группировки),
- примените критерии в условии having, чтобы отфильтровать сгруппированные результаты,
- удалите все столбцы, но те, которые указаны в столбцах результатов запросов, создавая те, которые являются вычисленными выражениями.
- примените порядок, указанный в инструкции по order by.
Никакой реальный SQL-движок не делает этого, но он должен вести себя так, как если бы это произошло. Ваша агрегированная функция вычисляется всего один раз вместе с любыми другими агрегатными функциями за один проход.