Продукт в GROUP BY с потенциальными нулями - PullRequest
0 голосов
/ 24 октября 2018

Поэтому я немного искал и обнаружил , что вы можете создать произведение строк в Oracle, используя GROUP BY и изящную математическую формулу: exp(sum(ln(some_col))).Это довольно круто, но, к сожалению, не работает, когда some_col потенциально равен нулю (потому что ln(0) невозможно, поскольку ln (x) - отрицательная бесконечность, когда приближается к нулю).

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

select
  a, b, c
  sum(d) d,
  sum(e) e,
  exp(sum(ln(f))) f
from x
group by a, b, c;

Очевидно, поскольку это произведение значений, если одно из них равно нулю, произведение будет равно нулю.Непосредственной мыслью было бы использовать case, но для этого требовалось бы, чтобы оператор case был на агрегированном значении или что-то в GROUP BY ... что это не так.Я не могу просто исключить эти строки, потому что мне все еще нужны sum(d) и sum(e).

Есть какие-нибудь мысли о хорошем способе сделать это, имея дело с потенциальными нулями?Я думал о чем-то, касающемся over(partition by ...), но на самом деле мои запросы группируются по 12 столбцам и объединяются еще 20 столбцов.Этот запрос может показаться ужасным, но если это единственное решение, я полагаю, у меня нет выбора.

Дополнительный вопрос: есть ли какая-то конкретная причина, по которой в Oracle нет функции продукта?Похоже, было бы так просто включить такую ​​вещь, как sum is.

Примечание: Это Oracle 12c.

Пример:

Если бы у меня была такая таблица ввода (в соответствии с запросом выше):

| a   | b   | c   | d | e | f |
+-----+-----+-----+---+---+---+
| foo | bar | hoo | 1 | 2 | 2 |
| foo | bar | hoo | 3 | 4 | 3 |
| foo | bar | hoo | 2 | 5 | 0 |
| foo | bar | mee | 1 | 2 | 2 |
| foo | bar | mee | 3 | 4 | 3 |

Я бы ожидал, что вывод будет выглядеть так:

|  a  |  b  |  c  | d | e  | f |
+-----+-----+-----+---+----+---+
| foo | bar | hoo | 6 | 11 | 0 |
| foo | bar | mee | 4 | 6  | 6 |

Однако, поскольку третья строка имеет0 для f, мы, естественно, получаем ORA-01428: argument '0' is out of range для ln(0).

1 Ответ

0 голосов
/ 24 октября 2018

Во-первых, log(0) не является неопределенным - это отрицательная бесконечность.

Второе: в Oracle вы можете создать отрицательную бесконечность, но вам придется использовать BINARY_FLOAT.

select a, b, c,
       sum(d) d,
       sum(e) e,
       exp(sum(CASE WHEN f <> 0 THEN ln(f) ELSE -1/0F END)) f
  from x
  group by a, b, c;

Используя ваши данные, вы получите:

A   B   C   D   E   F
foo bar hoo 6   11  0
foo bar mee 4   6   6.0000001304324524E+000

Обратите внимание, что при введении логарифмов и функций мощности возникнут некоторые проблемы с округлением, но это, по крайней мере, должно помочь вам начать.

dbfiddle здесь

К ОТРИЦАТЕЛЬНОЙ БЕСКОНЕЧНОСТИ ... И ВНЕ !!!!!!

: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...