Как игнорировать пустые значения в агрегатных функциях (AVG) при использовании нескольких операторов case - PullRequest
0 голосов
/ 13 февраля 2019

Я использую сервер SQL, чтобы найти среднее значение для некоторых столбцов, но я хочу игнорировать любой столбец, который имеет значение 0 или ноль

Таблица, из которой я читаю:

Table

Мой запрос:

SELECT AVG(CASE WHEN [January-Margin] > 0 THEN [January-Margin] ELSE NULL END + CASE WHEN [February-Margin] > 0 THEN [February-Margin] ELSE NULL END) as [Margin-Average] FROM MyTable

При использовании нескольких выражений в функции AVG () столбец всегда возвращает NULL.Что я делаю не так?

ОБНОВЛЕНИЕ: Как отметил @Gordon Linoff - это проблема с добавлением, а не с агрегатной функцией.Кто-нибудь может предложить другой способ достижения желаемого результата?

ОБНОВЛЕНИЕ: Мой желаемый результат:

January-Margin  February-Margin March-Margin    AvgMargin
43.111          0.00            0.00            43.111
57.2897         0.00            0.00            57.2897
55.5352         56.8987         0.00            56.2169

Ответы [ 3 ]

0 голосов
/ 13 февраля 2019

Вы должны исключить значения в предложении where.Любая операция с нулями возвращает ноль.

(1 + null) = null;
(1 - null) = null;
(3 + 4 + 5 + null) / 4 = null; // that's AVG function, right there

Я нахожу ваш стол немного странным.Но в любом случае вы можете сделать вложенный выбор.

    select 
(select avg(january-margin) from table where isnull(january-margin,0) > 0) january-margin,
(select avg(february-margin) from table where isnull(february-margin,0) > 0) february-margin
from table

и т. Д.

Обратите внимание, что вам, вероятно, понадобится объединение с таблицей внешних запросов.

0 голосов
/ 13 февраля 2019

Как насчет CROSS APPLY и NullIf ()

Пример

Declare @YourTable Table ([January-Margin] money,[February-Margin] money,[March-Margin] money)  Insert Into @YourTable Values 
 (43.111,0,0)
,(57.289700,0,0)
,(55.535200,56.898700,0)

Select A.* 
      ,B.*
 From @YourTable A
 Cross Apply ( 
               Select AvgMargin = avg(Value)
                From (  values (NullIf([January-Margin] ,0))
                              ,(NullIf([February-Margin],0))
                              ,(NullIf([March-Margin]   ,0))
                      ) B1(value)
            )B

Возвращает

January-Margin  February-Margin March-Margin    AvgMargin
43.111          0.00            0.00            43.111
57.2897         0.00            0.00            57.2897
55.5352         56.8987         0.00            56.2169
0 голосов
/ 13 февраля 2019

Хммм, я думаю, вам может понадобиться заменить 0. Проблема с добавлением, а не средним:

AVG(CASE WHEN [January-Margin] > 0 THEN [January-Margin] ELSE 0 END +
    CASE WHEN [February-Margin] > 0 THEN [February-Margin] ELSE 0 END
   ) as [Margin-Average]

Если все равно 0, тогда используйте NULLIF(), чтобы игнорировать эти строки:

AVG(NULLIF(CASE WHEN [January-Margin] > 0 THEN [January-Margin] ELSE 0 END +
           CASE WHEN [February-Margin] > 0 THEN [February-Margin] ELSE 0 END, 0
          )
   ) as [Margin-Average]

Однако в вашем вопросе таких примеров нет.

РЕДАКТИРОВАТЬ:

Вы просто хотите это?

(AVG(NULLIF([January-Margin], 0) + AVG(NULLIF([February-Margin], 0))) / 2

Этовроде как среднее значение значений в двух столбцах, где значения не 0.

Фактическое среднее будет:

(SUM(NULLIF([January-Margin], 0) + SUM(NULLIF([February-Margin], 0))) / (COUNT(NULLIF([January-Margin], 0)) + COUNT(NULLIF([February-Margin], 0)))
...