|
За период получить количество дней, в которые проходило хотя бы одно мероприятие | ☑ | ||
---|---|---|---|---|
0
presto29
12.02.18
✎
00:32
|
Есть регистр сведений - непериодический и без регистратора. Одно измерение "Мероприятие" (справочник) и два ресурса "ДатаНачала" и "ДатаОкончания". В регистре хранятся записи о проводимых мероприятиях, которые во времени могут пересекаться, накладываться и т.д.
Задача: Нужно ЗАПРОСОМ за период получить количество дней, в которые проходило хотя бы одно мероприятие. P.S. Мероприятие может начаться в прошлом месяце и переходить в текущий, также может начинаться в текущем и уходить в следующий, а может вообще начаться в прошлом и длиться аж до следующего. Например: Если за выбранный период проходило два мероприятия, в один и тот же период, длительностью три дня, то запрос должен вернуть «3». А если эти мероприятия проходили в разное время и не пересекались, то запрос должен вернуть «6». |
|||
1
dmg515
12.02.18
✎
00:37
|
Выбрать все даты за требуемый период из регламентированного календаря, соединить внутренним соединением с РС по Дата <=РС.ДатаОкончания И Дата>=РС.ДатаНачала
|
|||
2
presto29
12.02.18
✎
00:40
|
спасибо (1)
|
|||
3
Tateossian
12.02.18
✎
00:59
|
Вот:
ВЫБРАТЬ "Мероприятие: пьянка" Мероприятие, ДАТАВРЕМЯ(2018,1,9) НачДата, ДАТАВРЕМЯ(2018,1,11) КонДата ПОМЕСТИТЬ ГлавТаблица ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "Корпоратив" Мероприятие, ДАТАВРЕМЯ(2018,1,8) НачДата, ДАТАВРЕМЯ(2018,1,15) КонДата ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "Дедлайн" Мероприятие, ДАТАВРЕМЯ(2018,1,17) НачДата, ДАТАВРЕМЯ(2018,2,15) КонДата; ВЫБРАТЬ ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, aa.a * 1000 + bb.b * 100 + cc.c * 10 + dd.d) КАК Период ПОМЕСТИТЬ Периоды ИЗ (ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9) КАК aa, (ВЫБРАТЬ 0 КАК b ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9) КАК bb, (ВЫБРАТЬ 0 КАК c ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9) КАК cc, (ВЫБРАТЬ 0 КАК d ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9) КАК dd ГДЕ aa.a * 1000 + bb.b * 100 + cc.c * 10 + dd.d <= РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ); ВЫБРАТЬ Периоды.Период, ГлавТаблица.Мероприятие ПОМЕСТИТЬ ВсеДниМероприятий ИЗ ПЕРИОДЫ КАК ПЕРИОДЫ ЛЕВОЕ СОЕДИНЕНИЕ ГлавТаблица ГлавТаблица ПО (Периоды.Период МЕЖДУ ГлавТаблица.НачДата И ГлавТаблица.КонДата) ГДЕ НЕ ГлавТаблица.Мероприятие ЕСТЬ NULL ; ВЫБРАТЬ КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Период) ИЗ ВсеДниМероприятий |
|||
4
Fram
12.02.18
✎
02:41
|
ВЫБРАТЬ
Мероприятия.Мероприятие КАК Мероприятие, ВЫБОР КОГДА Мероприятия.ДатаНачала < &НачДата ТОГДА &НачДата ИНАЧЕ Мероприятия.ДатаНачала КОНЕЦ КАК ДатаНачала, ВЫБОР КОГДА Мероприятия.ДатаОкончания > &КонДата ТОГДА &КонДата ИНАЧЕ Мероприятия.ДатаОкончания КОНЕЦ КАК ДатаОкончания ПОМЕСТИТЬ МероприятияЗаПериод ИЗ РегистрСведений.Мероприятия КАК Мероприятия ГДЕ Мероприятия.ДатаОкончания >= &НачДата И Мероприятия.ДатаНачала <= &КонДата ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ ВЫБОР КОГДА МИНИМУМ(МероприятияДоп.ДатаНачала) <= Мероприятия.ДатаНачала ТОГДА 0 ИНАЧЕ 1 + РАЗНОСТЬДАТ(Мероприятия.ДатаНачала, ЕСТЬNULL(МИНИМУМ(МероприятияДоп.ДатаНачала), Мероприятия.ДатаОкончания), ДЕНЬ) КОНЕЦ КАК Дней ПОМЕСТИТЬ ДнейВрем ИЗ МероприятияЗаПериод КАК Мероприятия ЛЕВОЕ СОЕДИНЕНИЕ МероприятияЗаПериод КАК МероприятияДоп ПО Мероприятия.Мероприятие = МероприятияДоп.Мероприятие И Мероприятия.ДатаОкончания > МероприятияДоп.ДатаНачала И Мероприятия.ДатаОкончания < МероприятияДоп.ДатаОкончания СГРУППИРОВАТЬ ПО Мероприятия.ДатаНачала, Мероприятия.ДатаОкончания ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ СУММА(ДнейВрем.Дней) КАК Дней ИЗ ДнейВрем КАК ДнейВрем |
|||
5
Fram
12.02.18
✎
02:42
|
(4) не проверял, но должно сработать
|
|||
6
Fram
12.02.18
✎
02:46
|
(6) 2 подзапрос надо сгруппировать по Мероприятия.Мероприятие. конструктор подвел
|
|||
7
Fram
12.02.18
✎
03:23
|
все таки, налажал. вот так будет правильнее
ВЫБРАТЬ РАЗЛИЧНЫЕ ВЫБОР КОГДА Мероприятия.ДатаНачала < &НачДата ТОГДА &НачДата ИНАЧЕ Мероприятия.ДатаНачала КОНЕЦ КАК ДатаНачала, ВЫБОР КОГДА Мероприятия.ДатаОкончания > &КонДата ТОГДА &КонДата ИНАЧЕ Мероприятия.ДатаОкончания КОНЕЦ КАК ДатаОкончания ПОМЕСТИТЬ Периоды ИЗ РегистрСведений.Мероприятия КАК Мероприятия ГДЕ Мероприятия.ДатаОкончания >= &НачДата И Мероприятия.ДатаНачала <= &КонДата ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ ВЫБОР КОГДА МИНИМУМ(ПериодыДоп.ДатаНачала) ЕСТЬ NULL ТОГДА 1 + РАЗНОСТЬДАТ(Периоды.ДатаНачала, Периоды.ДатаОкончания, ДЕНЬ) КОГДА МИНИМУМ(ПериодыДоп.ДатаНачала) <= Периоды.ДатаНачала ТОГДА 0 ИНАЧЕ РАЗНОСТЬДАТ(Периоды.ДатаНачала, МИНИМУМ(ПериодыДоп.ДатаНачала), ДЕНЬ) КОНЕЦ КАК Дней ПОМЕСТИТЬ ДнейВрем ИЗ Периоды КАК Периоды ЛЕВОЕ СОЕДИНЕНИЕ Периоды КАК ПериодыДоп ПО (Периоды.ДатаОкончания МЕЖДУ ПериодыДоп.ДатаНачала И ПериодыДоп.ДатаОкончания) СГРУППИРОВАТЬ ПО Периоды.ДатаНачала, Периоды.ДатаОкончания ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ СУММА(ДнейВрем.Дней) КАК Дней ИЗ ДнейВрем КАК ДнейВрем |
|||
8
presto29
13.02.18
✎
23:37
|
Tateossian (3) и Fram (4),(7), спасибо огромное за поддержку и подробный код!!! ;)
|
|||
9
presto29
16.02.18
✎
03:47
|
(7) не считает, а если править условие, то выдает общее количество.
Так как выбрать различные относиться уже просто к вычетанию между датами. вот как выбрать пересечение множеств без повторений? |
|||
10
Fram
16.02.18
✎
06:50
|
(9) да, похоже, не додумал немного.. давай, сам. там немного осталось уже.
или (3) юзай |
|||
11
Ildarovich
17.02.18
✎
19:18
|
Вот такой вариант будет работать без использования искусственной таблицы дат либо производственного календаря и в случае, когда занятость требуется с точностью до секунд узнать (в разности дат параметр тогда нужно будет поменять):
ВЫБРАТЬ ДАТАВРЕМЯ(2018, 2, 23) КАК ДатаНачала, ДАТАВРЕМЯ(2018, 2, 23) КАК ДатаОкончания
Запрос основан на идеях статьи http://catalog.mista.ru/public/92490/ .
Во вложенном запросе определяются края "островов". Расстояние от начала времен до левого края вычитается, а до правого края - прибавляется. Тут не учитывается требование попадания мероприятий в заданный интервал, но это нетрудно решить предварительно (обрезав выходящие за край заданного интервала мероприятия). |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |