|
Пересечение периодов в запросе. | ☑ | ||
---|---|---|---|---|
0
qwasqu
24.11.16
✎
13:50
|
Здравствуйте.
Есть таблица, например: 01.01.16 - 10.03.16 01.02.16 - 20.03.16 30.03.16 - 15.04.16 10.04.16 - 12.04.16 11.04.16 - 25.04.16 30.04-16 - 10.05.16 В результате они должны схлопнуться в: 01.01.16 - 20.03.16 30.03.16 - 25.04.16 30.04-16 - 10.05.16 Вообще таблица может быть какой угодно. Я не нашел способа в запросе схлопнуть ее. Подскажите, если кто сталкивался. Спасибо. |
|||
1
Злопчинский
24.11.16
✎
13:54
|
задача определения пересечения периодов подробно рассмотрена на ИС у Ильдаровича - посмотри там, может найдешь полезное
|
|||
2
qwasqu
24.11.16
✎
14:09
|
(1) К сожалению у него не то, там он выбирает периоды, которые содержат дату.
ВЫБРАТЬ * ИЗ Дано ГДЕ &МоментВремени МЕЖДУ НачалоИнтервала И КонецИнтервала оптимизирует данный запрос. |
|||
3
azernot
24.11.16
✎
14:12
|
ВЫБРАТЬ
ДАТАВРЕМЯ(2016, 1, 1) КАК ДатаНачала, ДАТАВРЕМЯ(2016, 3, 10) КАК ДатаОкончания ПОМЕСТИТЬ ТаблицаПериодов ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 2, 1), ДАТАВРЕМЯ(2016, 3, 20) ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 3, 30), ДАТАВРЕМЯ(2016, 4, 15) ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 4, 10), ДАТАВРЕМЯ(2016, 4, 12) ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 4, 11), ДАТАВРЕМЯ(2016, 4, 25) ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 4, 30), ДАТАВРЕМЯ(2016, 5, 10) ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ РАЗЛИЧНЫЕ ДатыНачала.ДатаНачала КАК ДатаНачала, МАКСИМУМ(ВЫБОР КОГДА ДатыНачала.ДатаОкончания > ДатыОкончания.ДатаОкончания ТОГДА ДатыНачала.ДатаОкончания ИНАЧЕ ДатыОкончания.ДатаОкончания КОНЕЦ) КАК ДатаОкончания ПОМЕСТИТЬ ДатыНачалаСМаксимальнойДатойОкончания ИЗ ТаблицаПериодов КАК ДатыНачала ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТаблицаПериодов КАК ДатыОкончания ПО ДатыНачала.ДатаНачала <= ДатыОкончания.ДатаНачала И ДатыНачала.ДатаОкончания >= ДатыОкончания.ДатаНачала СГРУППИРОВАТЬ ПО ДатыНачала.ДатаНачала ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ РАЗЛИЧНЫЕ МИНИМУМ(ДатыНачала.ДатаНачала) КАК ДатаНачала, ДатыОкончания.ДатаОкончания ИЗ ДатыНачалаСМаксимальнойДатойОкончания КАК ДатыНачала ВНУТРЕННЕЕ СОЕДИНЕНИЕ ДатыНачалаСМаксимальнойДатойОкончания КАК ДатыОкончания ПО ДатыНачала.ДатаОкончания >= ДатыОкончания.ДатаНачала И ДатыНачала.ДатаНачала <= ДатыОкончания.ДатаНачала СГРУППИРОВАТЬ ПО ДатыОкончания.ДатаОкончания УПОРЯДОЧИТЬ ПО ДатаНачала |
|||
4
azernot
24.11.16
✎
14:14
|
(3) + Не, облажался, не универсальный запрос
|
|||
5
newbling
24.11.16
✎
14:16
|
я делал недавно.
| И ВЫБОР | КОГДА TopSports_СкидкаВЗависимостиОтВеличиныОборота.ПериодОкончанияДействия = ДАТАВРЕМЯ(1, 1, 1) | ТОГДА ВЫБОР | КОГДА &ПериодОкончанияДействия = ДАТАВРЕМЯ(1, 1, 1) | ТОГДА ИСТИНА | ИНАЧЕ TopSports_СкидкаВЗависимостиОтВеличиныОборота.Период <= &ПериодОкончанияДействия | КОНЕЦ | ИНАЧЕ ВЫБОР | КОГДА &ПериодОкончанияДействия = 0 | ТОГДА TopSports_СкидкаВЗависимостиОтВеличиныОборота.ПериодОкончанияДействия >= &Период | ИНАЧЕ TopSports_СкидкаВЗависимостиОтВеличиныОборота.ПериодОкончанияДействия >= &Период | И TopSports_СкидкаВЗависимостиОтВеличиныОборота.Период <= &ПериодОкончанияДействия | КОНЕЦ | КОНЕЦ |
|||
6
newbling
24.11.16
✎
14:17
|
с учётом правой границы периода до бесконечности
|
|||
7
newbling
24.11.16
✎
14:18
|
Если не учитывать, то достаточно
ПериодОкончанияДействия >= &Периодначала И ПериодНачала <= &ПериодОкончанияДействия |
|||
8
d546
24.11.16
✎
14:18
|
(0) в исходных есть гарантия, что начало периода больше конца периода?
|
|||
9
newbling
24.11.16
✎
14:20
|
(5) (6) (7) пардон, задача немного другая
|
|||
10
newbling
24.11.16
✎
14:23
|
Хм, кажется, что проще циклом пробежаться, а ни в запросе мудрить.
|
|||
11
qwasqu
24.11.16
✎
14:23
|
(8) В таблице левая дата всегда меньше правой.
|
|||
12
newbling
24.11.16
✎
14:26
|
Я бы просто цикл сделал с конца.
|
|||
13
Ildarovich
24.11.16
✎
14:29
|
В статье http://catalog.mista.ru/public/460935/ есть задача 25,
а в статье http://catalog.mista.ru/public/306536/ - задача 14, которые ИМЕЮТ ОТНОШЕНИЕ к рассматриваемому вопросу. Проблема задачи (0) в том, что периоды могут пересекаться, а 14 и 25 на это не рассчитаны. Поэтому я бы сделал так: сначала соединением с таблицей дат периода (получить ее можно многими способами, хоть из календаря) нашел все даты без повторений, а затем применил бы решение из 14. |
|||
14
newbling
24.11.16
✎
14:34
|
(13) по быстродействию быстрее выгрузить, отработать ручками в цикле, а потом опять грузануть. И логически проще.
|
|||
15
Ildarovich
24.11.16
✎
14:49
|
Вот все решение:
ВЫБРАТЬ
ВЫБРАТЬ
ВЫБРАТЬ
|
|||
16
azernot
24.11.16
✎
14:50
|
Вот запрос
ВЫБРАТЬ ДАТАВРЕМЯ(2016, 1, 1) КАК ДатаНачала, ДАТАВРЕМЯ(2016, 3, 10) КАК ДатаОкончания ПОМЕСТИТЬ ТаблицаПериодов ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 2, 1), ДАТАВРЕМЯ(2016, 3, 20) ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 3, 30), ДАТАВРЕМЯ(2016, 4, 15) ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 4, 10), ДАТАВРЕМЯ(2016, 4, 12) ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 4, 11), ДАТАВРЕМЯ(2016, 4, 25) ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(2016, 4, 30), ДАТАВРЕМЯ(2016, 5, 10) ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ РАЗЛИЧНЫЕ ДатыНачала.ДатаНачала КАК ДатаНачала, МАКСИМУМ(ВЫБОР КОГДА ДатыНачала.ДатаОкончания > ДатыОкончания.ДатаОкончания ТОГДА ДатыНачала.ДатаОкончания ИНАЧЕ ДатыОкончания.ДатаОкончания КОНЕЦ) КАК ДатаОкончания ПОМЕСТИТЬ ДатыНачалаСМаксимальнойДатойОкончания ИЗ ТаблицаПериодов КАК ДатыНачала ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТаблицаПериодов КАК ДатыОкончания ПО ДатыНачала.ДатаНачала <= ДатыОкончания.ДатаНачала И ДатыНачала.ДатаОкончания >= ДатыОкончания.ДатаНачала СГРУППИРОВАТЬ ПО ДатыНачала.ДатаНачала ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ РАЗЛИЧНЫЕ МИНИМУМ(ВЫБОР КОГДА ДатыОкончания.ДатаНачала < ДатыНачала.ДатаНачала ТОГДА ДатыОкончания.ДатаНачала ИНАЧЕ ДатыНачала.ДатаНачала КОНЕЦ) КАК ДатаНачала, ДатыОкончания.ДатаОкончания КАК ДатаОкончания ПОМЕСТИТЬ ДатаОкончанияСМинимальнойДатойНачала ИЗ ДатыНачалаСМаксимальнойДатойОкончания КАК ДатыОкончания ВНУТРЕННЕЕ СОЕДИНЕНИЕ ДатыНачалаСМаксимальнойДатойОкончания КАК ДатыНачала ПО ДатыОкончания.ДатаНачала <= ДатыНачала.ДатаОкончания И ДатыОкончания.ДатаОкончания >= ДатыНачала.ДатаОкончания СГРУППИРОВАТЬ ПО ДатыОкончания.ДатаОкончания ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ ДатаОкончанияСМинимальнойДатойНачала.ДатаНачала, ДатаОкончанияСМинимальнойДатойНачала.ДатаОкончания ИЗ ДатаОкончанияСМинимальнойДатойНачала КАК ДатаОкончанияСМинимальнойДатойНачала ЛЕВОЕ СОЕДИНЕНИЕ ДатаОкончанияСМинимальнойДатойНачала КАК ДатаОкончанияСМинимальнойДатойНачала1 ПО (ДатаОкончанияСМинимальнойДатойНачала.ДатаНачала > ДатаОкончанияСМинимальнойДатойНачала1.ДатаНачала И ДатаОкончанияСМинимальнойДатойНачала.ДатаОкончания < ДатаОкончанияСМинимальнойДатойНачала1.ДатаОкончания ИЛИ ДатаОкончанияСМинимальнойДатойНачала.ДатаНачала >= ДатаОкончанияСМинимальнойДатойНачала1.ДатаНачала И ДатаОкончанияСМинимальнойДатойНачала.ДатаОкончания < ДатаОкончанияСМинимальнойДатойНачала1.ДатаОкончания ИЛИ ДатаОкончанияСМинимальнойДатойНачала.ДатаНачала > ДатаОкончанияСМинимальнойДатойНачала1.ДатаНачала И ДатаОкончанияСМинимальнойДатойНачала.ДатаОкончания <= ДатаОкончанияСМинимальнойДатойНачала1.ДатаОкончания) ГДЕ ДатаОкончанияСМинимальнойДатойНачала1.ДатаНачала ЕСТЬ NULL УПОРЯДОЧИТЬ ПО ДатаОкончанияСМинимальнойДатойНачала.ДатаНачала Я вроде бы дыр не нашёл |
|||
17
azernot
24.11.16
✎
14:52
|
(15) Добавь период с 01.01.16 по 31.12.16.
Не сработает. |
|||
18
d546
24.11.16
✎
15:00
|
ВЫБРАТЬ
Данные.НачалоПериода, Данные.КонецПериода ПОМЕСТИТЬ ВТДанные ИЗ &Данные КАК Данные ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ Данные.НачалоПериода, Данные.КонецПериода ПОМЕСТИТЬ ВТБезПоглощаемых ИЗ ВТДанные КАК Данные ЛЕВОЕ СОЕДИНЕНИЕ ВТДанные КАК Данные2 ПО Данные.НачалоПериода > Данные2.НачалоПериода И Данные.КонецПериода < Данные2.КонецПериода ГДЕ Данные2.НачалоПериода ЕСТЬ NULL ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ РАЗЛИЧНЫЕ ЕСТЬNULL(НижняяГраница.НачалоПериода, БезПоглощаемых.НачалоПериода) КАК НачалоПериода, ЕСТЬNULL(ВерхняяГраница.КонецПериода, БезПоглощаемых.КонецПериода) КАК КонецПериода ИЗ ВТБезПоглощаемых КАК БезПоглощаемых ЛЕВОЕ СОЕДИНЕНИЕ ВТБезПоглощаемых КАК ВерхняяГраница ПО БезПоглощаемых.НачалоПериода <= ВерхняяГраница.НачалоПериода И БезПоглощаемых.КонецПериода >= ВерхняяГраница.НачалоПериода И БезПоглощаемых.КонецПериода < ВерхняяГраница.КонецПериода ЛЕВОЕ СОЕДИНЕНИЕ ВТБезПоглощаемых КАК НижняяГраница ПО БезПоглощаемых.НачалоПериода <= НижняяГраница.КонецПериода И БезПоглощаемых.КонецПериода >= НижняяГраница.КонецПериода И БезПоглощаемых.НачалоПериода > НижняяГраница.НачалоПериода |
|||
19
d546
24.11.16
✎
15:01
|
как то так
|
|||
20
Ildarovich
24.11.16
✎
15:03
|
(17) Ну да, там максимум - 256 дней в периоде.
|
|||
21
azernot
24.11.16
✎
15:04
|
(18) Добавь период 01.01.16 - 30.03.16
Не сравботает |
|||
22
d546
24.11.16
✎
15:06
|
(21) :)
|
|||
23
Ildarovich
24.11.16
✎
18:42
|
+(20) Ограничение 256 дат легко преодолеть, нарастив искусственную таблицу чисел. Если же вообще без нее, то вот вариант с использованием нарастающего итога:
ВЫБРАТЬ
На четыре строчки длиннее, чем (16), нужно подсократить. Но зато показывает, что задачу можно решить за линейное время, если использовать идеи из http://catalog.mista.ru/public/201526/ . |
|||
24
Ildarovich
25.11.16
✎
20:33
|
+(23) Вот самый короткий на текущий момент вариант. На 12 строчек короче, чем (16). Крайние точки выделяются условием несоединяемости не с каким интервалом, затем, в последнем запросе, они "спариваются":
ВЫБРАТЬ РАЗЛИЧНЫЕ
|
|||
25
Ildarovich
25.11.16
✎
21:16
|
+(24) Можно еще на шесть строк короче:
ВЫБРАТЬ РАЗЛИЧНЫЕ
|
|||
26
Лефмихалыч
25.11.16
✎
21:19
|
Ildarovich, снимаю шляпу, замерев в глубоком пардоне.
Я серьезно - мне нравятся эти штуки-дрюки с запросами, которые ты делаешь. Это офигенно! :) |
|||
27
Garykom
гуру
25.11.16
✎
21:29
|
(26) +1
ЗЫ Моя тоже сильно уважать умеющих делать "операции на гландах автогеном"... |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |