|
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
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |