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