Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Умножение записей - multiply / 8 сообщений из 8, страница 1 из 1
18.02.2020, 08:10
    #39927744
studieren
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение записей - multiply
Для решения одной специфической задачи мне пришлось группировать записи и умножить значения, а не просуммировать. Дело в том, что существует агрегатная функция суммирования (SUM), а вот умножения (Multiply) – нет. Как быть?
Чтобы решить данную задачу можно придумать функцию, можно также воспользоваться курсором. Но такие методы, как правило, работают медленно, если речь о большом количестве записей.
На просторах интернета я встретил самую необычную и изящную идею. Тот, кто додумался до этого, просто гений! Я бы сам никогда не додумался. Метод настолько очаровал меня, что я решил поделиться им. Оказывается агрегатной функции SUM вполне достаточно! Но вот только придётся изощряться. Дело в том, что сумма логарифмов с одинаковым основанием равняется как раз таки логарифму точно с таким основанием, но с умножением значений. Т.е.:
LN(A1) + LN(A2) + … + LN(An) = LN(A1*A2*…*An)
Чтобы избавиться от логарифма полученное таким образом значение потом нужно будет воздвигать в степень e.
Правда тут есть нюансы: все умножаемые числа должны быть больше 0, а для этого придётся брать только абсолютное значение и параллельно вести учёт знаков. Ну и в случае нулевого значения добавить «костыль».
Пример:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
WITH N AS (SELECT 1 AS ID, 2 AS VAL FROM DUAL
    UNION ALL SELECT 1, 115 FROM DUAL
    UNION ALL SELECT 1, -17 FROM DUAL
    UNION ALL SELECT 2,  19 FROM DUAL
    UNION ALL SELECT 2,  13 FROM DUAL
    UNION ALL SELECT 3,  24 FROM DUAL
    UNION ALL SELECT 3,  10 FROM DUAL
    UNION ALL SELECT 3,  15 FROM DUAL
    UNION ALL SELECT 3,   7 FROM DUAL
    UNION ALL SELECT 4,   1 FROM DUAL
    UNION ALL SELECT 4,   0 FROM DUAL)
SELECT ID, EXP(SUM(LN(CASE WHEN N.VAL=0 THEN 1 ELSE ABS(N.VAL) END)))
       * POWER(-1, (SUM(CASE WHEN N.VAL<0 THEN 1 ELSE 0 END)))
       * MIN(CASE WHEN N.VAL=0 THEN 0 ELSE 1 END) AS MULTIPLICATION
FROM N
GROUP BY ID
ORDER BY 1;


Выражение « POWER(-1, (SUM(CASE WHEN N.VAL<0 THEN 1 ELSE 0 END))) » необходимо чтобы следить за знаком (в случае если окажется отрицательное число).
Выражение « MIN(CASE WHEN N.VAL=0 THEN 0 ELSE 1 END) » необходимо для выяснения нет ли 0 среди умножаемых значений.
Если Вы точно знаете, что все умножаемые значения больше нуля, то и текст запроса будет проще.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
WITH N AS (SELECT 1 AS ID, 2 AS VAL FROM DUAL
    UNION ALL SELECT 1, 115 FROM DUAL
    UNION ALL SELECT 1,  17 FROM DUAL
    UNION ALL SELECT 2,  19 FROM DUAL
    UNION ALL SELECT 2,  13 FROM DUAL
    UNION ALL SELECT 3,  24 FROM DUAL
    UNION ALL SELECT 3,  10 FROM DUAL
    UNION ALL SELECT 3,  15 FROM DUAL
    UNION ALL SELECT 3,   7 FROM DUAL
    UNION ALL SELECT 4, 0.7 FROM DUAL
    UNION ALL SELECT 4,   1 FROM DUAL
    UNION ALL SELECT 4, 0.5 FROM DUAL)
SELECT ID, EXP(SUM(LN(N.VAL))) AS MULTIPLICATION
FROM N
GROUP BY ID
ORDER BY 1;



P.S.
Конечно же при этом нужно учесть, что если умножаемых чисел слишком много или же сами числа достаточно огромные, то может возникнуть ошибка переполнения.
...
Рейтинг: 0 / 0
18.02.2020, 08:24
    #39927749
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение записей - multiply
studieren
На просторах интернета я встретил самую ...
Для излияния открытий из интернета в интернет больше подходит форма личного блога, не форума. Впрочем, для данного форума воодушевление от очередного секрета Полишинеля не ново 39188 .
...
Рейтинг: 0 / 0
18.02.2020, 08:26
    #39927751
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение записей - multiply
studieren
Метод настолько очаровал меня, что я решил поделиться им.
Тут колумб и америго веспуччи отдыхают - именно ты, и неожиданно для всех, открыл америку.
...
Рейтинг: 0 / 0
18.02.2020, 08:33
    #39927756
studieren
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение записей - multiply
-2-,

Sorry. Я лично не видел этот топик раньше, хотя предварительно конечно же пользовался поиском. Стало быть плохо искал.
...
Рейтинг: 0 / 0
18.02.2020, 11:16
    #39927850
orawish
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение записей - multiply
studieren,

однозначно, плохо искал

stff групповая функция умножения
...
Рейтинг: 0 / 0
18.02.2020, 11:42
    #39927869
Щукина Анна
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение записей - multiply
studieren,

что-то напомнило....

YouTube Video
...
Рейтинг: 0 / 0
18.02.2020, 11:57
    #39927885
booby
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение записей - multiply
studieren,

studierenЧтобы решить данную задачу можно придумать функцию, можно также воспользоваться курсором. Но такие методы, как правило, работают медленно, если речь о большом количестве записей.

Для данного форума это на 100% ложное утверждение.
именно со специализированной пользовательской агрегатной функцией и работать будет удобнее,
и работать она будет гарантированно быстреe, по крайней мере на типе number.
Просто попробуй переписать это для случая применения в качестве аналитической функции - и так куча скобок,
а получится не читаемая кракозябра.
А вообще, имхо, такого рода штуки сами по себе не интересны, без воодушевляющего примера практически полезного использования.
...
Рейтинг: 0 / 0
18.02.2020, 12:06
    #39927890
booby
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение записей - multiply
booby,

удобнее, быстрее, ещё и точнее....
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Умножение записей - multiply / 8 сообщений из 8, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]