|
Можно ли запросом "свернуть" таблицу периодов? | ☑ | ||
---|---|---|---|---|
0
nvs
05.03.14
✎
08:20
|
Есть таблица из двух колонок: дата начала, дата окончания.
Надо свернуть таблицу так, чтобы в итоге остались непересекаемые между собой периоды. Например: периоды (01.01.2012 - 31.12.2012) и (01.01.2013 - 31.12.2013) должны сложиться в (01.01.2012 - 31.12.2013) периоды (01.01.2012 - 31.08.2012) и (01.07.2012 - 31.12.2012) должны свернуться в (01.01.2012 - 31.12.2012) Можно это сделать одним запросом? |
|||
1
butterbean
05.03.14
✎
08:32
|
(0) в твоем примере в итоге должен остаться только период (01.01.2012 - 31.12.2013) , правильно??
|
|||
2
shuhard
05.03.14
✎
08:34
|
(0)[Можно это сделать одним запросом?]
в общем случае - нет |
|||
3
catena
05.03.14
✎
09:19
|
А если периоды (01.01.2012 - 30.11.2012) и (01.01.2013 - 31.12.2013) ?
|
|||
4
mikecool
05.03.14
✎
09:20
|
(0) началопериода(год) и складывай
|
|||
5
nvs
05.03.14
✎
09:28
|
(1) - да в итоге один период останется, но в общем случае может быть множество непересекаемых периодов
(3) - в это м случае в итоговой таблице останется два периода, поскольку они не пересекаются и не соприкасаются (2) - тоже так кажется |
|||
6
catena
05.03.14
✎
10:20
|
Дайте примеров.
ВЫБРАТЬ Отрезки.А КАК А, Отрезки.Б КАК Б Поместить тз Из &Отрезки КАК Отрезки; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ тз.А, Максимум(тз2.Б) как Б Поместить тзОбъединенныеОтрезки Из тз КАК тз Левое Соединение тз как тз2 по (тз.Б >= ДобавитьКДате(тз2.А,День,-1) и тз.Б<=тз2.Б) Сгруппировать по тз.А; //////////////////////////////////////////////////////////////////////////////// Выбрать тз.А,тз.Б из тзОбъединенныеОтрезки как тз Левое Соединение тзОбъединенныеОтрезки как тз2 по (тз2.А<тз.А и тз.Б между тз2.А и тз2.Б)или(тз2.Б>тз.Б и тз.А между тз2.А и тз2.Б) Где тз2.А есть NULL |
|||
7
grigo
05.03.14
✎
10:29
|
Запросом в общем случае не решается.
|
|||
8
nvs
05.03.14
✎
10:32
|
(6) тут есть такая проблема: после первого выполнения данного запроса появится новая таблица периодов, которые также могут свернуться.
тут как-то булеву матрицу пересечений периодов надо строить или что-то в этом духе... |
|||
9
George Wheels
05.03.14
✎
10:36
|
(8) Сделай рекурсивный вызов или запрос в цикле. Сравнивай количество строк в ТЗ до обработки запросом и после. Если количество строк одинаково, то все периоды свернулись.
|
|||
10
catena
05.03.14
✎
11:01
|
(8)Не поняла, какая новая таблица? Я отбираю периоды, которые не вложены ни в один другой. Может где накосячила, дайте пример с недосвернутыми оборотами.
|
|||
11
kumena
05.03.14
✎
11:12
|
>>> периоды (01.01.2012 - 31.12.2012) и (01.01.2013 - 31.12.2013) должны сложиться в (01.01.2012 - 31.12.2013)
я такое делал запросом, результат можно посмотреть здесь http://www.kumena.ru/products/pechatnaya-forma-t-6-alternativnaya-zup-25 >>> периоды (01.01.2012 - 31.08.2012) и (01.07.2012 - 31.12.2012) должны свернуться в (01.01.2012 - 31.12.2012) думаю что тоже можно, но на халяву думать не интересно. |
|||
12
nvs
05.03.14
✎
11:22
|
(10)ваш алгоритм попробуйте на данных:
15.06.1987 21.04.2005 01.09.2000 01.05.2005 01.05.2005 31.08.2006 01.09.2006 11.09.2008 12.09.2008 31.12.2013 02.02.2009 01.02.2010 не срастается |
|||
13
catena
05.03.14
✎
12:40
|
(12)Ага.
Идея такая: тзТочки - собираем вообще все точки из наших периодов. тзОтрезкиПоПорядку - это все отрезки между нашими точками. тзНевходящиеОтрезки - находим среди отрезков по порядку те, которые не входят ни в один период. тзОбъединенныеОтрезки - вообще все варианты отрезков из наших точек, исключая отрезки, которые содержат никуда невходящие периоды. Итог - из всех отрезков выбираем самые большие, т.е. те, которые не входят ни в один другой отрезок.
|
|||
14
nvs
05.03.14
✎
13:20
|
(13) ага вроде рабочий вариант, сейчас еще по полочкам у себя в голове разложу запрос. Большое спасибо!
|
|||
15
kosts
05.03.14
✎
13:26
|
(0)
1. Создаем служебную ВТ с календарем. 2. Соединяем свои периоды с календарем. Для дней которые попали в период ставим в новом поле - 1, для тех дней, которые не попали - 0. Имеем календарь дней, назовем График. Например, получим: ДатаКалендаря, Поле1 1.1.2012, 0 2.1.2012, 0 3.1.2012, 1 4.1.2012, 1 5.1.2012, 0 6.1.2012, 0 3. Теперь соединяя и группируя Календарю из (1) и График из (2), условие соединения: к дню из календаря присоединим СЛЕДУЮЩИЙ день из Графика. Этим мы найдем граничные дни. Например должны получить: ДатаС, Поле1 1.1.2012, 0 3.1.2012, 1 5.1.2012, 0 4. Теперь соединяя саму с собой таблицу (3), группируя и минимизируя получим ДатаС, ДатаПо, Поле1 1.1.2012, 2.1.2012, 0 3.1.2012, 4.1.2012, 1 5.1.2012, 31.12.2012, 0 Может в (13) и такой же принцип, но анализировать лень... |
|||
16
catena
05.03.14
✎
13:30
|
(15)Не, вариант с подсчетом попадающих точек я не стала доделывать еще когда объем пересекающихся кубов считали. Не помню почему)
|
|||
17
kosts
05.03.14
✎
14:36
|
Другой вариант, найти периоды пустот
Затем из общего периода убрать пустоты, получим нужные итоговые периоды. (уже лень опять стало делать). |
|||
18
kosts
05.03.14
✎
14:59
|
(17)+ Т.е. что бы получить итоговые периоды нужно добавить 2 искусственных периода сверху и снизу и сделать совершенные аналогичные действия как в (17).
|
|||
19
nvs
05.03.14
✎
15:11
|
Вот чего я накопал:
Построил матрицу связей периодов (по вертикали периоды, по горизонтали тоже, элемент матрицы = 1 если периоды граничат или пересекаются, иначе 0). Далее необходимо построить матрицу достижимости Элементы матрицы достижимости по Алгоритму Флойда — Уоршелла for k = 1 to n for i = 1 to n for j = 1 to n W[i][j] = W[i][j] or (W[i][k] and W[k][j]) Далее клеим по этой матрице наши периоды и выбираем минимумы дат начала и максимум дат окончания только вот этот цикл в запросом выполнить надо |
|||
20
nvs
05.03.14
✎
15:12
|
и еще вариант:
ВЫБРАТЬ ДАТАВРЕМЯ(2014, 1, 1) КАК НачалоПериода, ДАТАВРЕМЯ(2014, 1, 5) КАК КонецПериода ПОМЕСТИТЬ Т ОБЪЕДИНИТЬ ВЫБРАТЬ ДАТАВРЕМЯ(2014, 1, 3), ДАТАВРЕМЯ(2014, 1, 10) ОБЪЕДИНИТЬ ВЫБРАТЬ ДАТАВРЕМЯ(2014, 1, 15), ДАТАВРЕМЯ(2014, 1, 25) ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ 0 КАК Цифра ПОМЕСТИТЬ СписокЦифр ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9 ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ РАЗЛИЧНЫЕ ДОБАВИТЬКДАТЕ(Т.НачалоПериода, ДЕНЬ, ЦифрыПорядка3.Цифра * 1000 + ЦифрыПорядка2.Цифра * 100 + ЦифрыПорядка1.Цифра * 10 + ЦифрыПорядка0.Цифра) КАК Дата ПОМЕСТИТЬ Т2 {ВЫБРАТЬ Дата} ИЗ Т КАК Т, СписокЦифр КАК ЦифрыПорядка3, СписокЦифр КАК ЦифрыПорядка2, СписокЦифр КАК ЦифрыПорядка1, СписокЦифр КАК ЦифрыПорядка0 ГДЕ ЦифрыПорядка3.Цифра * 1000 + ЦифрыПорядка2.Цифра * 100 + ЦифрыПорядка1.Цифра * 10 + ЦифрыПорядка0.Цифра <= РАЗНОСТЬДАТ(Т.НачалоПериода, Т.КонецПериода, ДЕНЬ) ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ Т2_11.Дата ПОМЕСТИТЬ НачалаПериодов ИЗ Т2 КАК Т2_11 ЛЕВОЕ СОЕДИНЕНИЕ Т2 КАК Т2_21 ПО (Т2_11.Дата = ДОБАВИТЬКДАТЕ(Т2_21.Дата, ДЕНЬ, 1)) ГДЕ Т2_21.Дата ЕСТЬ NULL ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ НачалаПериодов.Дата, КОЛИЧЕСТВО(РАЗЛИЧНЫЕ НачалаПериодов1.Дата) КАК НомерСтроки ПОМЕСТИТЬ НачалаПериодовСНомеромСтроки ИЗ НачалаПериодов КАК НачалаПериодов ВНУТРЕННЕЕ СОЕДИНЕНИЕ НачалаПериодов КАК НачалаПериодов1 ПО НачалаПериодов.Дата >= НачалаПериодов1.Дата СГРУППИРОВАТЬ ПО НачалаПериодов.Дата ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ Т2_11.Дата ПОМЕСТИТЬ КонцыПериодов ИЗ Т2 КАК Т2_11 ЛЕВОЕ СОЕДИНЕНИЕ Т2 КАК Т2_21 ПО (Т2_11.Дата = ДОБАВИТЬКДАТЕ(Т2_21.Дата, ДЕНЬ, -1)) ГДЕ Т2_21.Дата ЕСТЬ NULL ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ КонцыПериодов.Дата, КОЛИЧЕСТВО(РАЗЛИЧНЫЕ КонцыПериодов1.Дата) КАК НомерСтроки ПОМЕСТИТЬ КонцыПериодовСНомеромСтроки ИЗ КонцыПериодов КАК КонцыПериодов ВНУТРЕННЕЕ СОЕДИНЕНИЕ КонцыПериодов КАК КонцыПериодов1 ПО КонцыПериодов.Дата >= КонцыПериодов1.Дата СГРУППИРОВАТЬ ПО КонцыПериодов.Дата ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ НачалаПериодовСНомеромСтроки.Дата КАК НачалоПериода, КонцыПериодовСНомеромСтроки.Дата КАК КонецПериода ИЗ НачалаПериодовСНомеромСтроки КАК НачалаПериодовСНомеромСтроки ВНУТРЕННЕЕ СОЕДИНЕНИЕ КонцыПериодовСНомеромСтроки КАК КонцыПериодовСНомеромСтроки ПО НачалаПериодовСНомеромСтроки.НомерСтроки = КонцыПериодовСНомеромСтроки.НомерСтроки |
|||
21
catena
06.03.14
✎
06:35
|
Вариант (15) будет выглядеть так:
Выбрать 0 как ч поместить линейка1 объединить все выбрать 1 объединить все выбрать 2 объединить все выбрать 3 объединить все выбрать 4;
|
|||
22
APXi
06.03.14
✎
07:56
|
Интересно как потом такие запросы сопровождать, особенно если нет описания.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |