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

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

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

Выбрать
Т1.*,
Сумма(Т2.Сумма) КАК СуммаНарастающимИтогом//включая текущую
Из Т как Т1
соединение Т как Т2
Т1.ПолеCортировки >= Т2.ПолеCортировки
Сгруппировать по
Т1.*
10 fisher
 
27.07.21
17:50
(9) У него небольшая хитрость в задачке. Ему нужен в том числе и тот документ, который превысит сумму. Ну, как я понял. Поэтому придется в два этапа.
11 fisher
 
27.07.21
17:53
В первый этап найти документ, который превышает.
И во второй - выбрать документы со стартового по него включительно.
И придется заложиться на отсутствие нескольких документов в одну секунду.
12 RomanYS
 
27.07.21
18:05
(11)
1. "Имеющие" вполне решает проблему в один проход
2. >>придется заложиться на отсутствие нескольких документов в одну секунду.
Это тоже не сложно обходится:
По Т1.Дата > Т2.Дата или (Т1.Дата = Т2.Дата и Т1.Ссылка >= Т2.Ссылка)
13 Said_We
 
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
14 Said_We
 
27.07.21
20:49
В (13) Нет от которого документа начиная должно считаться ("начиная с заданного"), но считаем что в data только такие и попадут.
Номер документа определяет какой документ раньше, а какой позже. Задача упрощена, без даты.
Сознательно предварительно не сворачивал data по doc, sum(s). Но условие задачи легко изменить и в во входных данных сразу сделать так, что бы по одному документу была одна строчка с суммой.
В чистом SQL не нужны никакие join, для решения данной задачи. И это действительно за один проход. А с JOIN это не за один проход. Но 1С по другому не умеет.
15 Said_We
 
27.07.21
21:01
(8) "и начинаем последовательно по дате создания перебирать назад, накапливая сумму, до тех пор пока количество в выбранных не превысит требуемое значение"

Тоже самое что в (13) только предварительное суммирование, что бы не было двух строк по одному документу, обратная сортировка по doc в конструкции over() и в конце сравнении не > 55, а <=55.
16 Said_We
 
27.07.21
21:03
(0) Как подробно условие в (0) написал, такие подробные ответы и получил. :-)
17 МихаилМ
 
27.07.21
21:10
18 Said_We
 
28.07.21
00:10
(17) А чего так сложно в первом видео задачу решают?
19 Said_We
 
28.07.21
00:12
(17) Во втором видео так классно показал, что я не увидел конечный текст запроса. Перескакивает с места на место и в конце вообще решил допилить консоль запросов. :-)
20 Лефмихалыч
 
28.07.21
00:34
(8) надо под фактическую недостачу реализаций подобрать? :)
21 Said_We
 
28.07.21
01:05
(17) По первой задачи можно как ниже, хотя это не лучший вариант - но он просто очень понятный.
with - генерация данных
LAG() предыдущая запись
LEAD() следующая запись

Для чего этот пример, не из 1С?
Что бы было понимание, что данные задачи решаются без JOIN, за один проход и не городя огород. Т.е. выполняется запрос максимально быстро, текст запроса очень короткий и легко читается.

with data as
    (Select '2017-01-10' as d, 'rabotaet' as s
    union all select '2017-02-23', 'rabotaet'
    union all select '2017-02-28', 'otpusk'
    union all select '2017-03-11', 'bolnichniy'
    union all select '2017-03-15', 'bolnichniy'
    union all select '2017-03-17', 'bolnichniy'
    union all select '2017-03-30', 'rabotaet'
    union all select '2017-04-02', 'rabotaet'
    union all select '2017-04-08', 'otpusk'
    union all select '2017-04-14', 'rabotaet'
    union all select '2017-04-28', 'uvolen'
    )
select
     t.d as dateN
    ,Cast(DateADD(day, -1, LEAD(t.d) OVER(ORDER BY t.d)) as date) dateK
    ,t.s
from
    (select
         t.d
        ,t.s
        ,LAG(t.s) OVER(ORDER BY t.d) prev_s
    from
        data as t
    ) as t
where
    t.s <> t.prev_s
    or t.prev_s is null
22 Said_We
 
28.07.21
01:37
к (21)
Cast(ХХХ as date) - выразить как короткая дата без времени.
DateADD() - прибавить к дате, day - дней, -1 количество, третий параметр сама дата.
or t.prev_s is null - у первой записи нет предыдущей записи и её необходимо включить в результат дополнительным условием.
23 Said_We
 
28.07.21
01:46
(21) О первый раз цензура!
Что не так?
24 Said_We
 
28.07.21
01:47
(21) [Сообщение скрыто] [Лефмихалыч, 28.07.21 - 01:28]
Что такая запись означает?
25 ildary
 
28.07.21
06:58
(24) не всегда скрытие сообщения - цензура, иногда скрывают длинные портянки кода, чтобы упростить читателям навигацию по сообщениям. Кому надо - развернёт.
26 Почему 1С
 
28.07.21
08:31
(0)Если кратко, советую - сделай перебор в коде, все эти выкрутасы с ФИФО в запросе - интересны чтобы размять мозг, но являются плохим, малопонятным кодом, я когда то тоже любил такие извращения, потом переписал в пользу понятности.
27 Said_We
 
28.07.21
09:02
(25) Мне кажется что кому надо, тот свернул и даже отображаться иначе текст запроса стал иначе. Удалены переносы строк в итоге не рабочий вариант.

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

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

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

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

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

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

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

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

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

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

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

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