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

8.3 Накопленный итог запросом

8.3 Накопленный итог запросом
Я
   ЭЦ
 
27.07.21 - 16:50
Господа.
Имеются документы реализации продукции.
В каждом документе отгружается произвольно е количество.
Требуется определить минимальный перечень последовательно созданных документов
начиная с заданного.
Сумма продукции в которых превышает заданное число.
Как это реализовать запросом.
Прошу подсказать.
Спасибо
   polosov
 
1 - 27.07.21 - 16:54
СКД такое умеет.
Я прям голым запросом это что-то интересное будет.
Это тестовое при приеме не работу?
   ЭЦ
 
2 - 27.07.21 - 16:57
Это последняя надежда - перед последовательным перебором документов вне запроса.
   Deal with it
 
3 - 27.07.21 - 16:59
(0) может через критерии отбора "Связанные документы", в значение указать исходный документ и там уже таблицы с товарами сравнивать
   Deal with it
 
4 - 27.07.21 - 17:00
правда не уверен, что в значение можно передать массив документов. Это проблемка
   mikecool
 
5 - 27.07.21 - 17:06
(0) ищи тета-соединение в запросе
   RomanYS
 
6 - 27.07.21 - 17:08
(0) последовательно созданных документов - это как?
Последовательно - это просто сортировка по дате документа или что-то более глубокое?

>>начиная с заданного.
Документ один и задаётся параметром? Или нужно все последоваельности найти?
   Ёпрст
 
7 - 27.07.21 - 17:08
   ЭЦ
 
8 - 27.07.21 - 17:22
(6) Задаем документ.
и начинаем последовательно по дате создания перебирать назад, накапливая сумму, до тех пор пока количество в выбранных не превысит требуемое значение
   RomanYS
 
9 - 27.07.21 - 17:36
(8) тогда да, классика, ссылок полно

Навскидку что-то подобное

Выбрать
Т1.*,
Сумма(Т2.Сумма) КАК СуммаНарастающимИтого//включая текущую

Из Т как Т1
соединение Т как Т2
Т1.ПолеCортировки >= Т2.ПолеCортировки
Сгруппировать по
Т1.*
   fisher
 
10 - 27.07.21 - 17:50
(9) У него небольшая хитрость в задачке. Ему нужен в том числе и тот документ, который превысит сумму. Ну, как я понял. Поэтому придется в два этапа.
   fisher
 
11 - 27.07.21 - 17:53
В первый этап найти документ, который превышает.
И во второй - выбрать документы со стартового по него включительно.
И придется заложиться на отсутствие нескольких документов в одну секунду.
   RomanYS
 
12 - 27.07.21 - 18:05
(11)
1. "Имеющие" вполне решает проблему в один проход
2. >>придется заложиться на отсутствие нескольких документов в одну секунду.
Это тоже не сложно обходится:
По Т1.Дата > Т2.Дата или (Т1.Дата = Т2.Дата и Т1.Ссылка >= Т2.Ссылка)
   Said_We
 
13 - 27.07.21 - 20:33
(0)
Не знаю что за структура документа реализация. Предположил что есть табличная часть в которой есть сумма s. ss - сумма нарастающим итогом.
Можно без with, но пусть будет, отделим сами данные от алгоритма.
55 - это та самая сумма более которой считается превышение.

with data as
    (Select 1 as doc, 10 as s
    union all select 1, 15
    union all select 1, 25
    union all select 1, 5
    union all select 2, 10
    union all select 2, 5
    union all select 3, 1
    union all select 3, 3
    )
select
     t.doc
    ,Max(t.ss) as ss
from
    (select
        doc
        ,s
        ,sum(s) over(order by doc, s) as ss
    from
        data
    ) as t
where
    t.ss > 55
group by
    t.doc
   Said_We
 
14 - 27.07.21 - 20:49
В (13) Нет от которого документа начиная должно считаться ("начиная с заданного"), но считаем что в data только такие и попадут.
Номер документа определяет какой документ раньше, а какой позже. Задача упрощена, без даты.
Сознательно предварительно не сворачивал data по doc, sum(s). Но условие задачи легко изменить и в во входных данных сразу сделать так, что бы по одному документу была одна строчка с суммой.
В чистом SQL не нужны никакие join, для решения данной задачи. И это действительно за один проход. А с JOIN это не за один проход. Но 1С по другому не умеет.
   Said_We
 
15 - 27.07.21 - 21:01
(8) "и начинаем последовательно по дате создания перебирать назад, накапливая сумму, до тех пор пока количество в выбранных не превысит требуемое значение"

Тоже самое что в (13) только предварительное суммирование, что бы не было двух строк по одному документу, обратная сортировка по doc в конструкции over() и в конце сравнении не > 55, а <=55.
   Said_We
 
16 - 27.07.21 - 21:03
(0) Как подробно условие в (0) написал, такие подробные ответы и получил. :-)
   МихаилМ
 
17 - 27.07.21 - 21:10
»
   Said_We
 
18 - 28.07.21 - 00:10
(17) А чего так сложно в первом видео задачу решают?
   Said_We
 
19 - 28.07.21 - 00:12
(17) Во втором видео так классно показал, что я не увидел конечный текст запроса. Перескакивает с места на место и в конце вообще решил допилить консоль запросов. :-)
   Лефмихалыч
 
20 - 28.07.21 - 00:34
(8) надо под фактическую недостачу реализаций подобрать? :)
   Said_We
 
21 - 28.07.21 - 01:05
»
   Said_We
 
22 - 28.07.21 - 01:37
к (21)
Cast(ХХХ as date) - выразить как короткая дата без времени.
DateADD() - прибавить к дате, day - дней, -1 количество, третий параметр сама дата.
or t.prev_s is null - у первой записи нет предыдущей записи и её необходимо включить в результат дополнительным условием.
   Said_We
 
23 - 28.07.21 - 01:46
(21) О первый раз цензура!
Что не так?
   Said_We
 
24 - 28.07.21 - 01:47
(21) [Сообщение скрыто] [Лефмихалыч, 28.07.21 - 01:28]
Что такая запись означает?
   ildary
 
25 - 28.07.21 - 06:58
(24) не всегда скрытие сообщения - цензура, иногда скрывают длинные портянки кода, чтобы упростить читателям навигацию по сообщениям. Кому надо - развернёт.
   Почему 1С
 
26 - 28.07.21 - 08:31
(0)Если кратко, советую - сделай перебор в коде, все эти выкрутасы с ФИФО в запросе - интересны чтобы размять мозг, но являются плохим, малопонятным кодом, я когда то тоже любил такие извращения, потом переписал в пользу понятности.
   Said_We
 
27 - 28.07.21 - 09:02
(25) Мне кажется что кому надо, тот свернул и даже отображаться иначе текст запроса стал иначе. Удалены переносы строк в итоге не рабочий вариант.

Вместо
") as t
where"

Отображается
") as twhere"

В тексте вместо:
"
* with - генерация данных
* LAG() предыдущая запись
* LEAD() следующая запись
"

Отображается:
"with - генерация данныхLAG() предыдущая запись LEAD() следующая запись"
   fisher
 
28 - 28.07.21 - 09:10
(12) > "Имеющие" вполне решает проблему в один проход
В один "проход" не решает. Без подзапросов не обойтись.
Решало бы, если достаточно было получить документы ДО превышения предела накопительного итога. А какое ты условие поставишь, чтобы в выборку попал дополнительно только первый документ, который его превышает?
   Said_We
 
29 - 28.07.21 - 09:12
(28) Подзапросы практически не увеличивают время выполнения запроса. Но увеличивают читабельность и помогают избавится от копипаста.
   fisher
 
30 - 28.07.21 - 09:13
(29) А пиво не только вредно, но и полезно.
 
 
   RomanYS
 
31 - 28.07.21 - 09:15
(28)>> А какое ты условие поставишь, чтобы в выборку попал дополнительно только первый документ, который его превышает?
Буду собирать сумму нарастающим итогом БЕЗ текущего документа, для этого "<=" в соединениях заменяется на "<"
   fisher
 
32 - 28.07.21 - 09:20
(31) И верно. Чет тупанул.
   Said_We
 
33 - 28.07.21 - 09:25
(30) Если вот такое первого запроса засунуть в подзапрос, то не будет не будет копипаста логики "Выбор когда....". Читается легче и корректируется при необходимости в одном месте. Меньше ошибок, так как меньше копипаста.

Выбрать
   Выбор
     когда т.а<0 Тогда
        "а"
     когда т.а>=0 И т.а<10 Тогда
        "ж"
     иначе
        "й"
   конец как а
  ,т2.ф
ИЗ
   ВТ_Данные как т
LEFT JOIN ВТ_2 как т2
по
   Выбор
     когда т.а<0 Тогда
        "а"
     когда т.а>=0 И т.а<10 Тогда
        "ж"
     иначе
        "й"
   конец в (ж,й)
   И т.к = т2
   fisher
 
34 - 28.07.21 - 09:30
(33) Во-первых, ты делаешь общие выводы на основании частного случая. А во-вторых, подзапросы и временные таблицы - не совсем одно и то же.
   Said_We
 
35 - 28.07.21 - 09:36
В (0) формулируется задача
В (5) дается как вариант решения с помощью "тета-соединение в запросе".
В (17) даются ссылки что это такое "тета-соединение в запросе" в каких-то примерах.
В (21) по задачи из первой ссылки в (17) даётся вариант решения без "тета-соединение в запросе".

Далее посты (17) и (21) скрываются.

Не увидел я нарушения. Но есть как есть. Сколько людей столько и мнений.

(34) Написано в (30) "Без подзапросов не обойтись." - как будто, это какое-то зло.
"А во-вторых, подзапросы и временные таблицы - не совсем одно и то же." - а где написано что это одно и то же.
   Малыш Джон
 
36 - 28.07.21 - 09:45
(35) >>как будто, это какое-то зло

Подзапросы в соединениях в подавляющем количестве случаев - это зло.
   fisher
 
37 - 28.07.21 - 09:49
(35) Появление подзапросов как таковых в данном контексте - синоним усложнения логики запроса. "Многоэтажная" декларация требуемого результата. Это то, что подразумевал я. Диалог с RomanYS шел в контексте решения задачи с помощью максимально простой декларации. Мне казалось, что упростить нельзя. RomanYS показал, что можно. Мы с ним друг-друга поняли. Твой пример в (33) подразумевает использование временных таблиц для упрощения декларации. Ну или я тебя не понял. Короче, с тобой мы друг друга не поняли. Ну и фиг с ним. Бывает.
   Said_We
 
38 - 28.07.21 - 09:59
(36) "Твой пример в (33) подразумевает использование временных таблиц для упрощения декларации" - в моем примере нет временных таблиц. Первый запрос засовывается в подзапрос.
Примерно вот так я имел ввиду:

Выбрать
    т.с
  ,т2.ф
Из
(Выбрать
      Выбор
         когда т.а<0 Тогда
            "а"
         когда т.а>=0 И т.а<10 Тогда
            "ж"
         иначе
            "й"
      конец как с
     ,т.к
    ИЗ
       ВТ_Данные как т) как т
LEFT JOIN ВТ_2 как т2
по
   т.с в (ж,й)
   И т.к = т2
   Said_We
 
39 - 28.07.21 - 10:03
(36) Да ладно.
Иногда они ускоряют время выполнения итогового запроса, так как в соединении участвует не вся таблица, а только её часть, которая предварительно в подзапросе обрезалась в условии ГДЕ, например.

Замер двух запросов. Неожиданный результат
   Малыш Джон
 
40 - 28.07.21 - 10:08
(39) Специально написал "в подавляющем количестве случаев".

Ну и читаемость подзапросы вместо временных таблиц адски ухудшают.
   fisher
 
41 - 28.07.21 - 10:09
(38) Ок. Я подразумевал другой случай. Как раз не попадающий под "практически не увеличивают время выполнения запроса. Но увеличивают читабельность и помогают избавится от копипаста". А тот, когда это чистое усложнение при возможности решить задачу более простым способом.
   Said_We
 
42 - 28.07.21 - 10:13
(40) Если временные таблицы достаточно большие, то это может существенно увеличивать время выполнение запроса, чем без них. Тратится время на создание временной таблицы.
Тут только вопрос на сколько медленнее в конкретном случае. Если не критично, то используют временные таблицы. Критично обычно на больших базах.
   Said_We
 
43 - 28.07.21 - 10:18
(40) "Ну и читаемость подзапросы вместо временных таблиц адски ухудшают." - ухудшает читабельность и скорость выполнения запросов - беднота языка запросов в 1С.
В (21) как раз пример, который показывает как просто решается задача в SQL по сравнению с первым видео в (17). т.е. как можно иногда обходится без "тета-соединение в запросе", да и вообще без JOIN.
   Said_We
 
44 - 28.07.21 - 10:24
(40) В (13) тоже решение задачи, но задачи в (0) без JOIN.
   Лефмихалыч
 
45 - 28.07.21 - 11:20
(23) оффтоп. Твой запрос решает не задачу автора, а отвечает на какой-то влужупук набежавших персонажей (сам запрос и его корректность в рамках него самого я не обсуждаю).
Да, конечно, чтобы решить задачу, надо как-то соединять таблицу саму с собой и максимумы-минимумы-тыдык-тыдык-и-оконные-функции-если-есть - это все и так понятно. Но задачи автора это не решает, а только в сторону от нее уводит.
   Said_We
 
46 - 28.07.21 - 11:24
(45) Ok


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