Вход | Регистрация
 

Произведение чисел в запросе

Произведение чисел в запросе
Я
   mzelensky
 
04.05.21 - 16:21
Доброго времени суток.

Допустим на каком-то этапе запроса имеем таблицу с 2 колонками "Тип" (строка) и "Коэф" (число)

Тип   | Коэф
------|-------
Тип1  |   5
Тип2  |   1
Тип3  |   10

Нужно перемножить числа из колонки "Коэф" данной таблицы и вывести итоговый результат. Т.е. по примеру выше должно быть выведено "50"

Вопрос - как это сделать исключительно средствами запроса?

Пока в голову приходят только решения с промежуточной обработкой результата.
   acht
 
1 - 04.05.21 - 16:33
Ограничения на коэффициенты какое-нибудь есть? Типа "целое и диапазона"?
   Сергей Д
 
2 - 04.05.21 - 16:38
А в самом деле, почему нет такой функции...
http://www.sql-tutorial.ru/ru/book_product_of_column_values.html
   ДенисЧ
 
3 - 04.05.21 - 16:43
(2) Зато тангенсы есть...
   Ненавижу 1С
 
4 - 04.05.21 - 16:49
Сейчас не взлетит. Но обещают логарифм и экспоненту завести. Тогда можно с ними через сумму.

https://wonderland.v8.1c.ru/blog/novye-funktsii-yazyka-zaprosov-i-sistemy-komponovki-dannykh/

А вообще произведение будет погрешность большую давать
   shuhard
 
5 - 04.05.21 - 17:13
(4) ещё немного и будет нам T-SQL =)
   pechkin
 
6 - 04.05.21 - 17:46
произведения в колонке - такого даже в самом скл нет
   acht
 
7 - 04.05.21 - 18:46
(4) > Сейчас не взлетит.

Чой-та?
Если как следует заипацо и разложить ln и exp в какой-нибудь ряд Тейлора до приемлимой точности, то вполне.
   mzelensky
 
8 - 04.05.21 - 19:10
(1) Дробные числа - 12,2
   mzelensky
 
9 - 04.05.21 - 19:12
(4)(6) Мне сейчас надо.

Пока видится только вариант - выгрузить результат запроса (это СКД) в таблицу, обойти и вычислить произведение коэффичиентов, а потом результат загрузить обратно в СКД (в другйо макет) и уже через него сделать вывод в табличный документ
   acht
 
10 - 04.05.21 - 23:36
(9) > это СКД
А говорил, что в запросе...
RTFM, наверно, https://infostart.ru/1c/articles/1116759/ в части "ГрупповаяОбработка"
   Ненавижу 1С
 
11 - 05.05.21 - 00:28
(9) интересно накуа?
   Said_We
 
12 - 05.05.21 - 01:09
(0) Произведение коэффициентов?
Произведение может приводить к переполнению разрядности поля если числа, которые необходимо умножить хотя бы двузначные и таких чисел в по количеству 10-20 штук.

Если принять что коэффициентов, которые тебе необходимо перемножать не более 10 строк по каждому виду, то можно ИЗВРАТИТЬСЯ и сделать как ниже, НО лучше так НЕ делать.
SQL в 1С очень убогий, поэтому приходится извращаться, что бы не использовать "SELECT exp(SUM(log(value)))..." с учетом отрицательных чисел и null.
Оконных функций нет и АВТОНОМЕРЗАПИСИ() при сортировке можно использовать только при "ВЫБРАТЬ ПЕРВЫЕ МНОГО". Поэтому такой ужасссс ниже и ограничение в использовании!!!!
Если будет 11 строк по коэффициенту, то будет неверный результат умножения.

ВЫБРАТЬ
    1 КАК Коэф,
    10 КАК Сумма
ПОМЕСТИТЬ ВТ_Данные

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    1,
    2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    1,
    2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    1,
    -4

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    1,
    5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    2,
    -2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    2,
    3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    2,
    -5
;
////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ ПЕРВЫЕ 1316134911
    ВТ_Данные.Коэф КАК Коэф,
    ВТ_Данные.Сумма КАК Сумма,
    АВТОНОМЕРЗАПИСИ() КАК нпп
ПОМЕСТИТЬ ВТ_ДанныеСорт
ИЗ
    ВТ_Данные КАК ВТ_Данные

УПОРЯДОЧИТЬ ПО
    Коэф,
    Сумма
;

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
    т1.Коэф КАК Коэф,
    т1.Сумма КАК Сумма,
    т1.нпп - т2.нпп + 1 КАК НПП
ПОМЕСТИТЬ ВТ_Данные_НПП
ИЗ
    ВТ_ДанныеСорт КАК т1
        ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
            т.Коэф КАК Коэф,
            МИНИМУМ(т.нпп) КАК нпп
        ИЗ
            ВТ_ДанныеСорт КАК т
        
        СГРУППИРОВАТЬ ПО
            т.Коэф) КАК т2
        ПО т1.Коэф = т2.Коэф
;

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
    т.Коэф КАК Коэф,
    ЕСТЬNULL(т.Мн1, 1) * ЕСТЬNULL(т.Мн2, 1) * ЕСТЬNULL(т.Мн3, 1) * ЕСТЬNULL(т.Мн4, 1) * ЕСТЬNULL(т.Мн5, 1) * ЕСТЬNULL(т.Мн6, 1) * ЕСТЬNULL(т.Мн7, 1) * ЕСТЬNULL(т.Мн8, 1) * ЕСТЬNULL(т.Мн9, 1) * ЕСТЬNULL(т.Мн10, 1) КАК ПроизведениеМаксДесятиСтрок,
    т.Мн1 КАК Мн1,
    т.Мн2 КАК Мн2,
    т.Мн3 КАК Мн3,
    т.Мн4 КАК Мн4,
    т.Мн5 КАК Мн5,
    т.Мн6 КАК Мн6,
    т.Мн7 КАК Мн7,
    т.Мн8 КАК Мн8,
    т.Мн9 КАК Мн9,
    т.Мн10 КАК Мн10
ИЗ
    (ВЫБРАТЬ
        т.Коэф КАК Коэф,
        МАКСИМУМ(ВЫБОР
                КОГДА т.НПП = 1
                    ТОГДА т.Сумма
                ИНАЧЕ NULL
            КОНЕЦ) КАК Мн1,
        МАКСИМУМ(ВЫБОР
                КОГДА т.НПП = 2
                    ТОГДА т.Сумма
                ИНАЧЕ NULL
            КОНЕЦ) КАК Мн2,
        МАКСИМУМ(ВЫБОР
                КОГДА т.НПП = 3
                    ТОГДА т.Сумма
                ИНАЧЕ NULL
            КОНЕЦ) КАК Мн3,
        МАКСИМУМ(ВЫБОР
                КОГДА т.НПП = 4
                    ТОГДА т.Сумма
                ИНАЧЕ NULL
            КОНЕЦ) КАК Мн4,
        МАКСИМУМ(ВЫБОР
                КОГДА т.НПП = 5
                    ТОГДА т.Сумма
                ИНАЧЕ NULL
            КОНЕЦ) КАК Мн5,
        МАКСИМУМ(ВЫБОР
                КОГДА т.НПП = 6
                    ТОГДА т.Сумма
                ИНАЧЕ NULL
            КОНЕЦ) КАК Мн6,
        МАКСИМУМ(ВЫБОР
                КОГДА т.НПП = 7
                    ТОГДА т.Сумма
                ИНАЧЕ NULL
            КОНЕЦ) КАК Мн7,
        МАКСИМУМ(ВЫБОР
                КОГДА т.НПП = 8
                    ТОГДА т.Сумма
                ИНАЧЕ NULL
            КОНЕЦ) КАК Мн8,
        МАКСИМУМ(ВЫБОР
                КОГДА т.НПП = 9
                    ТОГДА т.Сумма
                ИНАЧЕ NULL
            КОНЕЦ) КАК Мн9,
        МАКСИМУМ(ВЫБОР
                КОГДА т.НПП = 10
                    ТОГДА т.Сумма
                ИНАЧЕ NULL
            КОНЕЦ) КАК Мн10
    ИЗ
        ВТ_Данные_НПП КАК т
    
    СГРУППИРОВАТЬ ПО
        т.Коэф) КАК т
   Said_We
 
13 - 05.05.21 - 01:11
Максимально в подзапросы для читабельности. Можно было этим не заниматься, но не для себя же писал, а что бы (0) смог разобраться.
   Said_We
 
14 - 05.05.21 - 01:21
(2) В книге-статье по ссылке говориться, что автор не знает есть ли SQL сервер, который поддерживает агрегатную функцию умножения.
Точно есть. Я с таким сталкивался лет 15 назад - название сервера не помню уже. Какой-то экзотический.

Умножение коэффициентов из задач про бухгалтерию на вскидку вспомнил только одну. Это расчет среднего для отпуска при нескольких повышениях ЗП в расчетном периоде. Оклад в этом случае умножался на все коэффициенты повышения оклада после периода начисления оклада и до окончания расчетного периода (бывает повышение и после окончания расчетного периода, но до начала отпуска).
Сейчас средний уже несколько иначе считается. Но когда-то было и так в том числе.
А так больше не приходилось сталкиваться.
   Said_We
 
15 - 05.05.21 - 01:58
(0) Кстати есть ещё один извращенский способ :-)
Номер Значение
1      -2
2       4
3     3.3
4    -0.1
...
N     0.8

То же есть ограничение, но суть в том что бы умножать первую и вторую строку, третью и четвертую, пятую и шестую. Полученный результат заново нумеровать и повторять. Повторив так десять раз получим 2 в десятой = 1024 строки. Т.е. ограничение не десять, умножаемых строк, а целых 1024.
Но это тоже ИЗВРАТ :-)
   Said_We
 
16 - 05.05.21 - 02:06
+ к (15) Если применить не к числам, а к строкам и не умножение, а конкатенацию, то можно складывать последовательно строки.
Так например регулярных выражений в SQL 1С нет, а иногда немного надо. Разбираем посимвольно строки, что-то делаем и собираем обратно. :-) Не всё можно сделать, но что-то можно. Например удалить из строки все символы из списка.
Работает не долго, при не больших объемах данных.
   DrZombi
 
17 - 05.05.21 - 06:31
(12) Все это баловство, вот где правда -> (4)
   mzelensky
 
18 - 05.05.21 - 08:59
(14) У меня тоже, более чем за 10 лет, ни разу такой потребности не вставало, а тут "НАДО". Зачем - объяснять не вижу смысла.

Предложенные варианты конечно тот еще изврат.

Попробую вариант в (10)
   mikecool
 
19 - 05.05.21 - 10:36
(18) если уж очень надо, то вариант с промежуточной ТЗ самый простой и в последующем - легко поддерживаемый
сделаешь то, что предлагает Said_We и через месяц не вспомнишь - что это за ахинея, также подумай о тех, кто придет после тебя
   mzelensky
 
20 - 05.05.21 - 10:55
(19) В варианте с промежуточной таблицей тоже есть минусы - получается нужно 2 макета СКД - один под первую выборку и выгрузку в ТЗ, а второй под финальный вывод в табличный документ. При этом нужно сохранить возможность изменения структуры отчета и возможность отборов (в пользовательском режиме), а это значит накладывать отборы нужно первый макет, а настраивать структуры по второму. Нечто подобное я уже реализовывал, но это тоже "гемор" и определенные ограничения.
   Ненавижу 1С
 
21 - 05.05.21 - 11:15
Короче в СКД можно так ресурсу сделать: ВычислитьВыражение("Exp(Сумма(Log(Значение)))")
У меня заработало, правда округление дикое
   Said_We
 
22 - 05.05.21 - 11:16
(18) И правильно. Я показал ИЗВРАТ, что бы в эту сторону поползновений не было. А то будешь искать варианты там где их нет. :-)
Да и условие странное, всё только языком запросов 1С, при условии, что язык запросов в 1С ооооочень сильно обрезан, по сравнению с тем, что поддерживают SQL-сервера.

Почему всё так плохо? Вся причина в файловой. Тянут этот прицеп - цена вопроса потеря функциональности.

(19) Не предлагал, а мягко показал, что вариант есть, но он настолько плохой, что его использовать не стоит. И несколько раз прямо об этом сказал и КРУПНО :-)

P.S.
Пора делать 9-ку без файловой :-) Продавать её принципиально по другому. Не нравится конфигуратор - в топку его. и т.д. Напробовали разных вариантов в 8.0, 8.1, 8.3 - пора что-то конечное делать.
   fisher
 
23 - 05.05.21 - 11:21
В СКД можно через функцию общего модуля выкрутиться в формуле ресурса.
   mzelensky
 
24 - 05.05.21 - 11:23
(21) Попробую. Спасибо.
   Said_We
 
25 - 05.05.21 - 11:26
(21) Встречал ещё такой вариант:
Oracle : EXP(SUM(LN(column)))   or  POWER(N,SUM(LOG(column, N)))
MSSQL  : EXP(SUM(LOG(column)))  or  POWER(N,SUM(LOG(column)/LOG(N)))
MySQL  : EXP(SUM(LOG(column)))  or  POW(N,SUM(LOG(N,column)))
   Said_We
 
26 - 05.05.21 - 17:20
(17) Понятно что баловство, но ждать пока будет реализовано в (4) можно и до китайской пасхи, а (0) нужно вчера.
То что заявлено, что будет реализовано, не факт что будет.

Опять же сделают эти функции и добавят кучу ограничений. "АВТОНОМЕРЗАПИСИ()" уже добавили и что - сильно всем помогает?
Зачем вводить ограничение использовать только во внутренних таблицах?
Зачем вводить возможность сортировки таких внутренних таблиц с "АВТОНОМЕРЗАПИСИ()" только если указано "ВЫБРАТЬ ПЕРВЫЕ N"?
Откуда они придумывают такие ограничения? Опять файловая? В топку файловую.
   DrZombi
 
27 - 06.05.21 - 06:22
(26) >>> АВТОНОМЕРЗАПИСИ

Да ни черта, о ней еще надо вспомнить.
Вот если допилят до (4), а еще если позволят условия в запросах выставлять более гибко, как в SQL.
Вот тогда и будет народ пользоваться.

Ну а если они еще и функции позволят писать, для запросов, то вообще будет суперски :)
   DrZombi
 
28 - 06.05.21 - 06:23
(21) Медленно.
   patapum
 
29 - 06.05.21 - 09:14
(0) Прикинуть реальное ограничение, сколько множителей будет, и заложить в запросе столько раз соединение с собой. И плюс еще пяток, для верности. Можно даже программно формировать текст запроса по числу необходимых соединений.
Не может же быть коэффициентов сто штук, реально длины числа не хватит.
   Said_We
 
30 - 06.05.21 - 12:15
(29) Соединение нужно только одно, и то только из-за того что нельзя нумеровать список по группировкам. Пример в (12) как раз без соединений. Каждое соединение это убийца производительности. Чем меньше джоинов, тем быстрее выполняется запрос.

(28) Конечно медленно. Это же обработка результата запроса уже не средствами SQL. Расчет для каждой строки проходит как отдельный вызов.
 
 
   Said_We
 
31 - 06.05.21 - 12:18
(29) Почему длины числа не хватит? А если коэффициенты вот такие:
1,2
0,8
0,87
1,11
1,02
0,98
0,65
0,95
1,22
1,15

Другими словами "болтаются" около единицы и их произведение стремиться к 1.
   Said_We
 
32 - 06.05.21 - 12:30
(19) "и через месяц не вспомнишь - что это за ахинея"

С ахинеей согласен на 100%.

С тем что не вспомнишь НЕ согласен. Запрос слишком прост, чтобы за минуту другую не понять, а тем более вспомнить что он делает.
   Said_We
 
33 - 06.05.21 - 13:01
+ (32)

1) ПОМЕСТИТЬ ВТ_Данные - это генерация самих данных. Запрос может быть любой и данные тоже.
2) ПОМЕСТИТЬ ВТ_ДанныеСорт - это добавление общей нумерации в поле НПП, но в обязательном порядке группировки по полю "Коэф", по сумме не обязательно.
3) ПОМЕСТИТЬ ВТ_Данные_НПП - это перенумерация таким образом, что бы для каждой группировки нумерация шла с 1.
Последний запрос добавляет поля - сколько необходимо 10, 15, 20... ещё ужаснее маразм :-) ... 100 При этом значение поля будет установлено в сумму только где номер по порядку суммы совпадает с номером колонки, в остальных случаях NULL. Разворачивание таблицы (нет PIVOT и UNPIVOT в 1С тем более). Далее МАХ() сворачивает таблицу так что по каждой группировке остается одна строка и много добавленных колонок. При этом NULL всегда меньше любого значения. Собственно поэтому NULL, а не кое-то число.
Далее приведение итоговый значений в свернутой таблице если они NULL к 1 и умножение колонок.

2) и 3) аналогичны одной записи "ROW_NUMBER() OVER(PARTITION BY Коэф ORDER BY Сумма)", но 1С так не позволяет. Оконных функций нет в 1С.

2) Коэф, сумма, НПП
1, 1, 1
1, 2, 2
1, 2, 3
1, 4, 4
2, 1, 5
2, 2, 6
2, 2, 7

2) Коэф, сумма, НПП
1, 1, 1
1, 2, 2
1, 2, 3
1, 4, 4
2, 1, 1 нумерация опять с 1
2, 2, 2
2, 2, 3

3) Коэф, сумма, НПП, мн1, мн2, мн3, мн4, мн5,...
1, 1, 1, 1, NULL, NULL, NULL, NULL,...
1, 2, 2, NULL, 2, NULL, NULL, NULL,...
1, 2, 3, NULL, NULL, 2, NULL, NULL,...
1, 4, 4, NULL, NULL, NULL, 4, NULL,...
2, 1, 1, 1, NULL, NULL, NULL, NULL,...
2, 2, 2, NULL, 2, NULL, NULL, NULL,...
2, 2, 3, NULL, NULL, 3, NULL, NULL,...

после сворачивания
Коэф, мн1, мн2, мн3, мн4, мн5,...
1, 1, 2, 2, 4, NULL,...
2, 1, 2, 3, NULL, NULL,...
После ЕСТЬNULL()
1, 1, 2, 2, 4, 1,...
2, 1, 2, 3, 1, 1,...
   Said_We
 
34 - 06.05.21 - 13:04
(19) теперь ахинею не забыть :-)
   mistеr
 
35 - 06.05.21 - 13:58
(24) Ты задачей-то поделись, где нужно умножение. Интересно же.

И почему непременно в запросе.
   Said_We
 
36 - 06.05.21 - 15:01
(35) Скорее всего там этого и не нужно. Или можно решить как-то иначе. Мне на вскидку пришла на ум только задача в (14).
Но в ней количество коэффициентов, которые необходимо умножить редко бывает более 1. Очень редко ЗП поднимают по всему предприятию или подразделениям более одного раза в 12 месяцев.
Её вообще редко поднимают группе сотрудников :-). Чаще увольняются сотрудники, а принимают новых уже на других условиях других сотрудников. ОК не мониторят среднюю ЗП постоянно, а делают это только когда вакансию не могут закрыть и ищут обоснования. А можно было бы в 90% и прошлых сотрудников сохранить, учить не надо, вникать не надо и т.д. :-) Но это уже совсем другая история....
   ILM
 
Модератор
37 - 07.05.21 - 06:06
(35) Состав изделия, где есть коэффициенты запуска (вероятность получения годного). Расчет затрат в ЖКХ, где сумма произведений и коэффициенты зависимости от типа строения и коммуникаций для оценки ремонта. В страховании есть такое. Даже симптоматику учитывать в медицине можно по влиянию на диагноз. Очень много прогнозных вещей есть в статистике с произведением строк, да и при контроле качества тоже. Это то, что вспомнилось за овер 30 лет работы.
   ILM
 
Модератор
38 - 07.05.21 - 06:13
(37) Да, на оракле можно было сделать собственные команды и применять их в запросах. 15 лет назад это делал, уже забыл вроде CREATE COMMAND и там описание.
   Said_We
 
39 - 07.05.21 - 11:15
(37) т.е. это все отрасли, где 1С не поможет, так как нет в запросах математических функций.
Т.е. 1С не применимо/ограничено применимо в таких отраслях как: Производство сложных устройств и механизмов, ЖКХ в части оценки затрат, Страхование, Медицина в части оценки симптоматики (то что сейчас как раз министерство здравоохранения хочет применить как помощь врачам при определении диагнозов - выдавать список возможных и вероятность + что допроверять, что бы что-то исключить или подтвердить).

Наверняка сюда можно будет добавить любую отрасль, где нужна статистика. Например образование.

Почему неприменимо и ограниченно применимо? На малых данных можно извращаться с получением результата запроса в ТЗ, обработка на алгоритмическом языке интерпретаторе результата. Засовыванием результата опять в менеджер временных таблиц. Запрос и ещё одно левое соединение и т.д.
На больших объемах это может оказаться очень долгим процессом. А на очень больших объемах в промежуточную ТЗ результат не засунуть - места не хватит. А SQL бы "схавал".

Повторюсь. Файловую версию в топку, она реально мешает ограничивая функциональность. Зачем тянуть этот разодранный мертвый хвост.
   mistеr
 
40 - 07.05.21 - 15:55
(38) CREATE OPERATOR :)
Ораклоидам привет!
   mistеr
 
41 - 07.05.21 - 15:57
> Зачем тянуть этот разодранный мертвый хвост.

Посчитай, сколько денег с пользователей, которые на ней сидят, и поймешь.
   Said_We
 
42 - 07.05.21 - 16:10
(41) Этим пользователям можно было предложить и серверный вариант. И специальную лицензию придумать и всё это по той же цене. Так что деньги тут не при чем совсем.


Список тем форума
 
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.