Как перемножить колонку нарастающие, запросом?

1. igormiro 714 16.11.18 11:25 Сейчас в теме
Как перемножить колонку нарастающие, запросом?
Строк в таблице может быть произвольно
Условие

ВЫБРАТЬ
 ДАТАВРЕМЯ(2018, 01,01),
 150

ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
 ДАТАВРЕМЯ(2017, 01,01),
 200
 ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
 ДАТАВРЕМЯ(2016, 01,01),
 30

ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
 ДАТАВРЕМЯ(2015, 01,01),
 10

Нужно
2015 10
2016 10 * 30
2017 10 * 30  * 200
2018 10 * 30  * 200 * 150
Показать
Вознаграждение за ответ
Показать полностью
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
9. ildarovich 7870 16.11.18 17:47 Сейчас в теме
(1) Думал над этим когда-то, нужно будет повспоминать, что тогда придумал и придумал ли что-нибудь вообще...

Сейчас думается, что будет работать способ из https://infostart.ru/public/201526/ при замене сложения на умножение.

Ограничение того метода в том, что число строк может быть очень большим, но все же не больше, чем некоторое конкретное число. Например, 1 000 000.
Думаю, что если вопрос практический, то умножать вряд ли требуется столько строчек - быстро наступит переполнение порядка.
Второе ограничение метода "Баттерфляй" - необходимость нумерации строк. Это можно сделать классическим нарастанием. А в последних версиях платформы - появившимся методом RowNumber() или как он там конкретно называется.
mifka186; +1 Ответить
10. spacecraft 16.11.18 18:09 Сейчас в теме
(9)
Сейчас думается, что будет работать способ из https://infostart.ru/public/201526/ при замене сложения на умножение.

проблема в том, что нет агрегатной функции произведение, в отличие от сложения.
11. ildarovich 7870 16.11.18 20:17 Сейчас в теме
(10) Ну, я имел ввиду не буквальное воспроизведение запроса, а собственно метод. В нем по сути складываются (а будут умножаться) пары строчек. Пары с одинаковыми старшими чем первый, двоичными разрядами. 1 и 2, 3 и 4, 5 и 6 и т.п.
В общем, нужно соблюсти принцип, а запись запроса адаптировать к задаче.
Наверное, лучше сделаю это сам, чтобы не разводить споры. Чуть позже.
Если устроят ограничения, упомянутые в (9).
12. ildarovich 7870 16.11.18 22:17 Сейчас в теме
+(9) Еще один вариант: Транзитивное замыкание. Сгодится при числе строк в группе до 100-500. Так как вычислительная сложность будет расти квадратично. Представить строки как вершины графа. Связи исходно задать по условию расположения строк рядом по порядку. То есть: 2015-2016, 2016-2017, 2017-2018. Находить длину пути как произведение длин путей дуг. Ну и поскольку результат не зависит от порядка вычислений, он окажется правильным. Но здесь будет избыточность в вычислениях. Чтобы определить произведение 10 * 30 * 200 * 150 будет считаться и 10 * (30 * 200 * 150) и (10 * 30) * (200 * 150) и (10 * 30 * 200) * 150.
Такой метод я уже кому-то предлагал. Считалось что-то типа скидок или вроде того. Сказали, что пригодилось, работает.

Можно еще функцию логарифма протабулировать.
r.zdorkin; +1 Ответить
13. ildarovich 7870 19.11.18 11:53 Сейчас в теме
+ (12) Чтобы не быть голословным, приведу конкретный запрос:
ВЫБРАТЬ ДАТАВРЕМЯ(2018, 1, 1) КАК Ключ, 2 КАК Сомножитель ПОМЕСТИТЬ Дано
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2017, 1, 1), 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 1, 1), 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2015, 1, 1), 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2014, 1, 1), 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2013, 1, 1), 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2012, 1, 1), 2
;
// Пролог: нумерация таблицы Дано в порядке возрастания ключа
ВЫБРАТЬ КОЛИЧЕСТВО(Слева.Ключ) КАК Номер, Дано.Ключ, Дано.Сомножитель
ПОМЕСТИТЬ Строй
ИЗ Дано КАК Слева ВНУТРЕННЕЕ СОЕДИНЕНИЕ Дано КАК Дано ПО Слева.Ключ <= Дано.Ключ
СГРУППИРОВАТЬ ПО Дано.Ключ, Дано.Сомножитель
;
// Пролог: формирование дуг и петель для каждой вершины, включая начальную нулевую
ВЫБРАТЬ Дано.Номер - 1 КАК НачалоДуги, Дано.Номер КАК КонецДуги, Дано.Сомножитель
ПОМЕСТИТЬ Раз
ИЗ Строй КАК Дано
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 0, 0, 1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Дано.Номер, Дано.Номер, 1
ИЗ Строй КАК Дано
;
// Рефрен: первое соединение дуг дает пути длины до 2 включительно
ВЫБРАТЬ Слева.НачалоДуги, Справа.КонецДуги, МИНИМУМ(Слева.Сомножитель * Справа.Сомножитель) КАК Сомножитель
ПОМЕСТИТЬ Два
ИЗ Раз КАК Слева ВНУТРЕННЕЕ СОЕДИНЕНИЕ Раз КАК Справа ПО Слева.КонецДуги = Справа.НачалоДуги
СГРУППИРОВАТЬ ПО Слева.НачалоДуги, Справа.КонецДуги
;
// Чтобы потом переиспользовать имя временной таблицы:
УНИЧТОЖИТЬ Раз;
// Рефрен: второе соединение дуг дает пути длины до 4 включительно
ВЫБРАТЬ Слева.НачалоДуги, Справа.КонецДуги, МИНИМУМ(Слева.Сомножитель * Справа.Сомножитель) КАК Сомножитель
ПОМЕСТИТЬ Раз 
ИЗ Два КАК Слева ВНУТРЕННЕЕ СОЕДИНЕНИЕ Два КАК Справа ПО Слева.КонецДуги = Справа.НачалоДуги
СГРУППИРОВАТЬ ПО Слева.НачалоДуги, Справа.КонецДуги
;
УНИЧТОЖИТЬ Два;
// Рефрен: третье соединение дуг дает пути длины до 8 включительно
ВЫБРАТЬ Слева.НачалоДуги, Справа.КонецДуги, МИНИМУМ(Слева.Сомножитель * Справа.Сомножитель) КАК Сомножитель
ПОМЕСТИТЬ Два
ИЗ Раз КАК Слева ВНУТРЕННЕЕ СОЕДИНЕНИЕ Раз КАК Справа ПО Слева.КонецДуги = Справа.НачалоДуги
СГРУППИРОВАТЬ ПО Слева.НачалоДуги, Справа.КонецДуги
;
УНИЧТОЖИТЬ Раз;
// Рефрен: четвертое соединение дуг дает пути длины до 16 включительно
ВЫБРАТЬ Слева.НачалоДуги, Справа.КонецДуги, МИНИМУМ(Слева.Сомножитель * Справа.Сомножитель) КАК Сомножитель
ПОМЕСТИТЬ Раз 
ИЗ Два КАК Слева ВНУТРЕННЕЕ СОЕДИНЕНИЕ Два КАК Справа ПО Слева.КонецДуги = Справа.НачалоДуги
СГРУППИРОВАТЬ ПО Слева.НачалоДуги, Справа.КонецДуги
;
УНИЧТОЖИТЬ Два;
// Рефрен: пятое соединение дуг дает пути длины до 32 включительно
ВЫБРАТЬ Слева.НачалоДуги, Справа.КонецДуги, МИНИМУМ(Слева.Сомножитель * Справа.Сомножитель) КАК Сомножитель
ПОМЕСТИТЬ Два
ИЗ Раз КАК Слева ВНУТРЕННЕЕ СОЕДИНЕНИЕ Раз КАК Справа ПО Слева.КонецДуги = Справа.НачалоДуги
СГРУППИРОВАТЬ ПО Слева.НачалоДуги, Справа.КонецДуги
;
УНИЧТОЖИТЬ Раз;
// Рефрен: шестое соединение дуг дает пути длины до 64 включительно
ВЫБРАТЬ Слева.НачалоДуги, Справа.КонецДуги, МИНИМУМ(Слева.Сомножитель * Справа.Сомножитель) КАК Сомножитель
ПОМЕСТИТЬ Раз 
ИЗ Два КАК Слева ВНУТРЕННЕЕ СОЕДИНЕНИЕ Два КАК Справа ПО Слева.КонецДуги = Справа.НачалоДуги
СГРУППИРОВАТЬ ПО Слева.НачалоДуги, Справа.КонецДуги
;
УНИЧТОЖИТЬ Два;
// Эпилог: результат выбирается из дуг, соединяющих нулевую и текущую вершину, в результате транзитивного замыкания 
ВЫБРАТЬ
	Дано.Ключ,
	Раз.Сомножитель КАК Произведение
ИЗ
	Строй КАК Дано
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Раз КАК Раз
		ПО (Раз.НачалоДуги = 0)
			И Дано.Номер = Раз.КонецДуги
УПОРЯДОЧИТЬ ПО
	Дано.Ключ
Показать
Запрос специально написан сжато, чтобы иметь лучшую обзорность. Кому так читать неудобно, может скопировать его к себе в консоль и распаковать конструктором. Первый запрос в пакете - формирование таблицы с данными для проверки. Для удобства считаются степени двойки, которые всем известны. Можно подставить любые числа.
В данном варианте записи может обрабатываться до 64 строк в группе. Если строк вдруг больше, нужно будет подобавлять рефренов. Каждый рефрен увеличивает максимальное число строк вдвое. Поэтому десять рефренов дадут 1024 строки. Это близко к пределу данного метода, поскольку тогда в последней таблице Раз будет порядка 500 000 строк.
Если строк больше, то стоит рассмотреть вариант из (9), который работает линейное время (!!!), но там запись сложнее.
Прикрепленные файлы:
spacecraft; +1 Ответить
2. JohnGalt 57 16.11.18 12:16 Сейчас в теме
Варианты
1. Сделать ваш запрос вложенным и перемножать в итоговом запросе.
2. Вместо объединения использовать вложенность или временную таблицу для каждого подзапроса
3. В СКД использовать вычислыемые поля.
4. В СКД добавить формулу на закладке "Ресурсы"
3. igormiro 714 16.11.18 13:13 Сейчас в теме
(2) Вот условие
 ВЫБРАТЬ 
ДАТАВРЕМЯ(2018, 01,01), 
150 

ОБЪЕДИНИТЬ ВСЕ 
ВЫБРАТЬ 
ДАТАВРЕМЯ(2017, 01,01), 
200 
ОБЪЕДИНИТЬ ВСЕ 
ВЫБРАТЬ 
ДАТАВРЕМЯ(2016, 01,01), 
30 

ОБЪЕДИНИТЬ ВСЕ 
ВЫБРАТЬ 
ДАТАВРЕМЯ(2015, 01,01), 
10 
Показать

Нужен результирующий оптимальный запрос
4. antz 16.11.18 13:31 Сейчас в теме
(3)

так, написал, но неправильно)
5. r.zdorkin 16.11.18 13:36 Сейчас в теме
(4)
у вас 2018 10 * 30 * 200 * 150 = 30000 что вроде явно не сходится
6. antz 16.11.18 13:39 Сейчас в теме
7. caponid 16.11.18 16:05 Сейчас в теме
Вопрос то провокационный....
Для языка запросов 1С простого решения не будет (нет функций экспоненты и нат логарифма)
8. igormiro 714 16.11.18 16:33 Сейчас в теме
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот