Имя: Пароль:
1C
 
Как сгруппировать записи по дате и еще одному условию?
,
0 RomaH
 
naïve
04.04.22
09:35
Есть таблица:
Начало периода - окончание периода - длина слота - количество слотов

зачастую начало периода - конец периода в последовательных записях (при сортировке по началу периода) выстраиваются в цепочку

как сгруппировать такие записи?

https://ibb.co/MRxdyM2
1 Вафель
 
04.04.22
09:41
https%3A%2F%2Fprofessorweb.ru%2Fmy%2Fsql-server%2Fwindow-functions%2Flevel3%2F3_11.php
2 2mugik
 
04.04.22
09:43
цепляй. Можно наверное какое-нить транзикативное замыкание приплести. На инфостарте иерархию так строить предлагали.
3 lEvGl
 
гуру
04.04.22
09:46
что значит сгруппировать, по какому признаку? по часам, или по чем
4 _Дайвер_
 
04.04.22
09:56
(3) Как из условий сказано в пределах дня по длине слота, вывести сумму по количеству слотов и выдать дату от и до группируемых строк
5 RomaH
 
naïve
04.04.22
09:57
6 lEvGl
 
гуру
04.04.22
10:12
(3) хрен знает, я из другого измерения видимо, из за преломления пространственно временного континуума не вижу таких условий
7 Вафель
 
04.04.22
10:37
(6) Задача называется "упаковка интервалов".
довольно таки не тривиальная задача
8 Ненавижу 1С
 
гуру
04.04.22
10:45
Выберите все начала интервалов, которые не входят в другие полуинтервалы вида (a,b].
Выберите все окончания интервалов, которые не входят в другие полуинтервалы вида [a,b).
Соедините их сгруппировав, например по началам интервалов, выбрав минимумы окончаний не меньших этих начал.
Применить все это с точностью до других разделителей (пользователей, отделов, других полей)
9 ДедМорроз
 
04.04.22
20:15
Во-первых,отсортировать по дате начала.
Далее,интервал сравниваем с предыдущим и определяем расстояние,если касаются и перекрываются,то ноль.
Ну и запист с нулем объединить с записью,где не ноль,тоже предыдущей.
По мойму,не сложно.
10 vde69
 
04.04.22
22:20
для 1с посмотри в сторону регистров расчета с их "вытеснением"
11 ДедМорроз
 
04.04.22
22:24
Вытеснение - это немного не то,это исключение интервала при наложении, а в (0) вопрос про непересекающиеся интервалы.
12 vde69
 
04.04.22
22:27
(11)
сначала надо провести вытеснение
потом смело объединять все где конец=началу
потом повторить сначала, до тех пор пока не исчерпапем все варианты объединения


патент довольно известный ("строй и перестраивай"), не думал, что его тут не вспомнят...
13 Said_We
 
04.04.22
23:12
(0) А что надо сделать с количеством слотов и длинной?
14 Said_We
 
04.04.22
23:15
(0) А на рисунке в первом выделении почему выделены строки начиная только с 11:20 до 11:40 ?
Почему не со строки 09:00?
15 Said_We
 
04.04.22
23:26
(5) Обратите внимание на скорость выполнения с оконными функциями.
Не совсем понял, почему нужно несколько итераций. В оконных функциях есть возможность получать предыдущую строку и следующую. Т.е. для каждой строки можно сразу видеть какое значение следующее и какое предыдущее. Можно лишние строки выкинуть сразу.

(6) В чем НЕ тривиальность. В ЗиУП такая задача решается постоянно и без оконных функций. Геморрой, много кода, не быстро работает, но работает.
16 Said_We
 
04.04.22
23:33
к (14) Увидел. За линией выделения время плохо видно. :-)
Как я понял, то "длина слота" поле группировки, а количество наверное сложить или максимум или минимум или не учитывать.
17 ДедМорроз
 
05.04.22
00:08
Пересекающиеся интервплы оконной функцией можно обрабатывать,если в наложении приоритет имеет следующий (более поздний по началу интервал) да и то,нужен стек,так как интервал может полностью содержаться в другом,да и количество наложений - величина не постоянная.

Там есть другой способ - все конечные точки в один массив,получаем массив интервалов от одной точки до другой.
Для каждого интервала определяем приоритетный отрезок из заданных интервалов,а потом уже снова соединяем последовательные отрезки,если они совпадают.
18 Said_We
 
05.04.22
00:09
(15) (7) Как пример задачи из ЗиУП. Тут нет даты окончания, но переделать запрос не сложно, условие дополнить сравнением даты начала и окончания периода...
+ В примере (0) дата+время, а не просто дата.
Так как есть дата конца периода всегда, не нужно вычислять дату окончания.

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

--------------------------------
* with - генерация данных, по существу создание временной таблицы. В 1С аналог "ПОМЕСТИТЬ".
* LAG() предыдущая запись
* LEAD() следующая запись
--------------------------------

В 1С, так как нет оконных функций, то предыдущую запись и следующую надо получать LEFT JOIN таблицы саму с собой. Что бы проще это было делать, то можно предварительно добавить поле Автонумирации и по нему соединение строить.
Выбрать первые 99999999 т.*, row_number() ПОМЕСТИТЬ ВТ_Данные из ВТ как т Упорядочить по ...
19 Said_We
 
05.04.22
00:12
(17) В задаче (0) нет пересекающихся периодов. Считай декомпозицию уже сделали и разбили на максимальное количество периодов. Далее в (0) как раз уже схлопнуть периоды.
20 Said_We
 
05.04.22
12:47
(0) А что надо сделать с количеством слотов?
С длиной вроде понятно - группировка/разрез это.
21 RomaH
 
naïve
05.04.22
12:48
(20) - сложить
Я не хочу быть самым богатым человеком на кладбище. Засыпать с чувством, что за день я сделал какую-нибудь потрясающую вещь — вот что меня интересует. Стив Джобс