[v8] Разбиение произвольного периода на интервалы (в запросе)

0. 862 16.08.12 15:43 Сейчас в теме
Аналог типовой функции РазложитьНаПериоды, только релизовано на языке запросов.

Перейти к публикации

Вознаграждение за ответ
Показать полностью
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. akomar 442 16.08.12 18:39 Сейчас в теме
Что такое РегистрСведений.РегламентированныйПроизводственныйКалендарь и где его найти?
2. Jetoo 55 17.08.12 06:38 Сейчас в теме
(1) akomar, вопрос скорее для пятницы! )))
3. cmd_vasec 34 17.08.12 08:51 Сейчас в теме
(1) akomar,
ЗУП тебе в помощь.
4. akomar 442 17.08.12 12:23 Сейчас в теме
Ну я бы сначало написал, что актуально для ЗУП.
5. the1 862 17.08.12 12:35 Сейчас в теме
Да ладно, в Бухии 2.0 он тоже есть. Думаю, что это стандарт 1С.
6. Maxik21 17.08.12 12:45 Сейчас в теме
РегламентированныйПроизводственныйКалендарь есть БУХ, ЗУП, УПП. Содержит все даты периода. Прикладное значение, к примеру, можно получить в запросе остатки на каждый день, неделю и т.д. в соединении с регистрами накопления и т.п. Тебе для чего нужно ?
7. petrov_al 10 17.08.12 18:57 Сейчас в теме
Автор, совет, изучай СКД и не понадобится тебе зуповский регистр который к тому же в бухе редко кто заполняет
8. the1 862 20.08.12 08:52 Сейчас в теме
(7) Спасибо за бесплатный совет, но не всё можно решить на СКД. Хотя, если подскажете, как вызвать СКД из общего модуля при проведении или расчете документа, буду очень признателен. К тому же язык запросов не отличается от используемого в СКД.

З.Ы. А регистр и не надо заполнять, он заполняется автоматически при обновлении ИБ.
9. KAPACEB.AA 20.08.12 11:40 Сейчас в теме
Спасибо. Правда, не совсем понял, зачем вторая временная таблица и левое соединение к ней в итоговом запросе. Может быть, так:

ВЫБРАТЬ
ПроизводственныйКалендарь.ДатаКалендаря,
ГОД(ПроизводственныйКалендарь.ДатаКалендаря) * 100 + МЕСЯЦ(ПроизводственныйКалендарь.ДатаКалендаря) КАК НомерМесяца
ПОМЕСТИТЬ ВТ_ДатыКалендаря
ИЗ
РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК ПроизводственныйКалендарь
ГДЕ
ПроизводственныйКалендарь.ДатаКалендаря МЕЖДУ &ПериодДействияНачало И &ПериодДействияКонец
;

ВЫБРАТЬ
МИНИМУМ(ВТ_ДатыКалендаря.ДатаКалендаря) КАК ДатаНачала,
МАКСИМУМ(ВТ_ДатыКалендаря.ДатаКалендаря) КАК ДатаОкончания
ИЗ
ВТ_ДатыКалендаря КАК ВТ_ДатыКалендаря
СГРУППИРОВАТЬ ПО
ВТ_ДатыКалендаря.НомерМесяца
корум; the1; +2 Ответить
10. the1 862 20.08.12 12:23 Сейчас в теме
(9) Mu_meson, да, так гораздо лучше =)
11. Akuji 17 22.08.12 16:21 Сейчас в теме
ПроизводственныйКалендарь для примера или он необходим по любому т.к. там все даты?
Интересует вопрос:
необходимо сгрупирровать по периодам (месяцам) данные по выборке документов, что бы в результате по куждому месяцу увидеть суммы.
И объеденить этот результат с еще одной таблицей регистра накопления с переодичностью месяц.

месяц сумма по документам
объеденить
месяц сумма по регистру
12. the1 862 23.08.12 10:41 Сейчас в теме
(11) Думаю, что ПроизводственныйКалендарь безболезненно можно заменить на выборку документов и группировать уже по дате документа, а не по дате календаря.
13. tormozit 6288 13.11.12 09:20 Сейчас в теме
Обман во многом. Не указана область применимости (типовые конфигурации). Не указана необходимость сначала заполнить регистр за тот период, для которого нужны интервалы. И т.д. В общем очень небрежно.

Вообще задачу разбиения на месяцы (и не только) легко можно решить и без регистра одним запросом (менее эффективно) или пакетным запросом (более эффективно). Здесь уже есть такие публикации.
japopov; herfis; ildarovich; +3 1 Ответить
14. ildarovich 7232 07.10.16 20:13 Сейчас в теме
Присоединюсь к замечанию в (13). Производственный календарь для решения этой задачи не требуется. Так можно и таблицу умножения в базу данных внести, если умножать разучиться.
16. the1 862 18.10.16 08:22 Сейчас в теме
(14) ildarovich, ну так ведь если инструмент (календарь) есть, то можно его использовать, не так ли? Все претензии разработчикам типовых :-)
17. ildarovich 7232 18.10.16 12:46 Сейчас в теме
(16) давайте я поясню свою мысль...

Предложенное вами решение без должного основания использует зависимости:
1) от наличия в составе конфигурации такого объекта как регистр сведений "РегламентированныйПроизводственныйКалендарь";
2) от его правильной заполненности на нужный период.
Если первая зависимость легко проверяется (при попытке использовать этот метод в конфигурации без календаря, вы просто получите ошибку), то вторая зависимость неприятнее. При частичной заполненности календаря вы получите ошибку в отчете, которую еще потребуется поискать.

Кроме того, используемый принцип совершенно зря перебирает все даты периода, когда из месяца требуется только одна запись. То есть работает в 30 раз медленнее возможного.

Вопрос, наверное не такой уж важный, но тут много начинающих, которые используют готовый код, никак его не осмысливая. В результате чего недостаточно проработанные, сделанные на скорую руку решения множатся. Авторы публикаций могли бы этому препятствовать, а вы, кажется, способствуете.

Кстати, если уж настаиваете на использовании календаря, могу предложить вот такой вариант из одного запроса:
ВЫБРАТЬ
	МИНИМУМ(Календарь.ДатаКалендаря) КАК ДатаНачала,
	МАКСИМУМ(Календарь.ДатаКалендаря) КАК ДатаОкончания
ИЗ
	РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь
ГДЕ
	Календарь.ДатаКалендаря МЕЖДУ &ПериодДействияНачало И &ПериодДействияКонец

СГРУППИРОВАТЬ ПО
	РАЗНОСТЬДАТ(&ПериодДействияНачало, Календарь.ДатаКалендаря, МЕСЯЦ)
Показать
Он короче и более универсальный - легко вид периода (день, месяц, год, квартал) поменять.

А вообще в свете вопроса (15) можно было бы и конкурс объявить на решение этой задачи без календаря.
json; the1; +2 Ответить
18. ildarovich 7232 18.10.16 12:51 Сейчас в теме
+(17) Требуется решить данную задачу
разбиения произвольного периода на интервалы в запросе
без использования регламентированного производственного календаря.
15. dock 43 17.10.16 10:49 Сейчас в теме
(13) tormozit, Замечательно, ну и где на инфостарте эти публикации ???
19. kasper076 77 18.10.16 14:44 Сейчас в теме
Запрос = Новый Запрос(	 
"ВЫБРАТЬ
|	НАЧАЛОПЕРИОДА(&НачПериода, МЕСЯЦ) КАК Период
|ИТОГИ ПО
|	Период ПЕРИОДАМИ(МЕСЯЦ, НАЧАЛОПЕРИОДА(&НачПериода, МЕСЯЦ), КОНЕЦПЕРИОДА(&КонПериода, МЕСЯЦ))");

Но потребуется постобработка.
20. ildarovich 7232 18.10.16 14:50 Сейчас в теме
(19) kasper076, хорошее решение, но нужно, чтобы результат можно было внутри запроса использовать, поэтому итоги не годятся
21. HanterVol 8 18.10.16 15:15 Сейчас в теме
Быстренько для не более 64 месяцев
ВЫБРАТЬ
	0 КАК Поле
ПОМЕСТИТЬ Числа

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	1

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	3
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	Числа1.Поле + 4 * Числа2.Поле + 16 * Числа3.Поле + 1 КАК Поле
ПОМЕСТИТЬ ВТ_64
ИЗ
	Числа КАК Числа1,
	Числа КАК Числа2,
	Числа КАК Числа3
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
	ВЫБОР
		КОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ) = КОНЕЦПЕРИОДА(&ДатаНачала, МЕСЯЦ)
			ТОГДА &ДатаНачала
		КОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ) >= КОНЕЦПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
			ТОГДА НАЧАЛОПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
		ИНАЧЕ НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ)
	КОНЕЦ КАК НачПериода,
	ВЫБОР
		КОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ) >= КОНЕЦПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
			ТОГДА &ДатаОкончания
		ИНАЧЕ КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ)
	КОНЕЦ КАК КонПериода
ИЗ
	ВТ_64 КАК ВТ_64

СГРУППИРОВАТЬ ПО
	ВЫБОР
		КОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ) >= КОНЕЦПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
			ТОГДА &ДатаОкончания
		ИНАЧЕ КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ)
	КОНЕЦ,
	ВЫБОР
		КОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ) = КОНЕЦПЕРИОДА(&ДатаНачала, МЕСЯЦ)
			ТОГДА &ДатаНачала
		КОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ) >= КОНЕЦПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
			ТОГДА НАЧАЛОПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
		ИНАЧЕ НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ)
	КОНЕЦ
Показать
22. ildarovich 7232 18.10.16 15:20 Сейчас в теме
(21) HanterVol, да, решение нужно примерно такое, если покороче нельзя
24. Ovrfox 14 18.10.16 15:37 Сейчас в теме
(21) HanterVol, Разве так не проще?
ВЫБРАТЬ
    0 КАК Поле
ПОМЕСТИТЬ Числа

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    1

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    3
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Числа1.Поле + 4 * Числа2.Поле + 16 * Числа3.Поле),Месяц) КАК Поле
ПОМЕСТИТЬ ВТ_64
ИЗ
    Числа КАК Числа1,
    Числа КАК Числа2,
    Числа КАК Числа3
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
    ВЫБОР
        КОГДА КОНЕЦПЕРИОДА(ВТ_64.Поле , МЕСЯЦ) = КОНЕЦПЕРИОДА(&ДатаНачала, МЕСЯЦ)
            ТОГДА &ДатаНачала
        КОГДА КОНЕЦПЕРИОДА(ВТ_64.Поле , МЕСЯЦ) >= КОНЕЦПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
            ТОГДА НАЧАЛОПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
        ИНАЧЕ ВТ_64.Поле
    КОНЕЦ КАК НачПериода,
    ВЫБОР
        КОГДА КОНЕЦПЕРИОДА(ВТ_64.Поле, МЕСЯЦ)>= КОНЕЦПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
            ТОГДА &ДатаОкончания
        ИНАЧЕ КОНЕЦПЕРИОДА(ВТ_64.Поле , МЕСЯЦ)
    КОНЕЦ КАК КонПериода
ИЗ
    ВТ_64 КАК ВТ_64

упорядочить по НачПериода
Показать
25. Ovrfox 14 18.10.16 15:49 Сейчас в теме
(24) Ovrfox, последний запрос лучше так
ВЫБРАТЬ РАЗЛИЧНЫЕ
    ВЫБОР
        КОГДА ВТ_64.Поле < &ДатаНачала
            ТОГДА &ДатаНачала
        ИНАЧЕ ВТ_64.Поле
    КОНЕЦ КАК НачПериода,
    ВЫБОР
        КОГДА ВТ_64.КонПериода > &ДатаОкончания
            ТОГДА &ДатаОкончания
        ИНАЧЕ ВТ_64.КонПериода
    КОНЕЦ КАК КонПериода
ИЗ
    (Выбрать ВТ_64.Поле, КОНЕЦПЕРИОДА(ВТ_64.Поле , МЕСЯЦ) как КонПериода ИЗ ВТ_64 где ВТ_64.Поле<&ДатаОкончания)КАК ВТ_64

упорядочить по НачПериода
Показать
Rainger; kkv90; +2 Ответить
46. ildarovich 7232 21.10.16 16:31 Сейчас в теме
Пора подводить итоги. Добавлю вознаграждение, съеденное временем. HanterVol предложил свой вариант первым, а потом добавил еще один интересный вариант решения. Но в итоге с небольшим перевесом (0,5:1,5) побеждает вариант (24) Ovrfox. Этот вариант самый простой и короткий.
23. HanterVol 8 18.10.16 15:21 Сейчас в теме
Думаю что можно.... но нужно уже думать :)))
Если только без группировки, но с отбором
"ВЫБРАТЬ
|	0 КАК Поле
|ПОМЕСТИТЬ Числа
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
|	1
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
|	2
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
|	3
|;
|
|////////////////////////////////////////////////////////////­////////////////////
|ВЫБРАТЬ
|	Числа1.Поле + 4 * Числа2.Поле + 16 * Числа3.Поле + 1 КАК Поле
|ПОМЕСТИТЬ ВТ_64
|ИЗ
|	Числа КАК Числа1,
|	Числа КАК Числа2,
|	Числа КАК Числа3
|;
|
|////////////////////////////////////////////////////////////­////////////////////
|ВЫБРАТЬ РАЗЛИЧНЫЕ
|	ВЫБОР
|		КОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ) = КОНЕЦПЕРИОДА(&ДатаНачала, МЕСЯЦ)
|			ТОГДА &ДатаНачала
|		КОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ) >= КОНЕЦПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
|			ТОГДА НАЧАЛОПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
|		ИНАЧЕ НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ)
|	КОНЕЦ КАК НачПериода,
|	ВЫБОР
|		КОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ) >= КОНЕЦПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
|			ТОГДА &ДатаОкончания
|		ИНАЧЕ КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, ВТ_64.Поле - 1), МЕСЯЦ)
|	КОНЕЦ КАК КонПериода
|ИЗ
|	ВТ_64 КАК ВТ_64
|ГДЕ
|	ВТ_64.Поле < РАЗНОСТЬДАТ(&ДатаНачала, &ДатаОкончания, МЕСЯЦ) + 2"
Показать
26. HanterVol 8 18.10.16 16:19 Сейчас в теме
Или в 2 Запроса
и с другим алгоритмом заполнения таблицы чисел (кому как нравится, я если честно предыдущий хреново понимаю)
ВЫБРАТЬ
	0 КАК Поле
ПОМЕСТИТЬ Цифры

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	1

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	4

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	7

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	8

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	9
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
	ВЫБОР
		КОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Числа1.Поле + 10 * Числа2.Поле), МЕСЯЦ) = НАЧАЛОПЕРИОДА(&ДатаНачала, МЕСЯЦ)
			ТОГДА &ДатаНачала
		КОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Числа1.Поле + 10 * Числа2.Поле), МЕСЯЦ) < НАЧАЛОПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
			ТОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Числа1.Поле + 10 * Числа2.Поле), МЕСЯЦ)
		ИНАЧЕ НАЧАЛОПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
	КОНЕЦ КАК Поле,
	ВЫБОР
		КОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Числа1.Поле + 10 * Числа2.Поле), МЕСЯЦ) >= КОНЕЦПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
			ТОГДА &ДатаОкончания
		ИНАЧЕ КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Числа1.Поле + 10 * Числа2.Поле), МЕСЯЦ)
	КОНЕЦ КАК Поле1
ИЗ
	Цифры КАК Числа1,
	Цифры КАК Числа2
ГДЕ
	КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Числа1.Поле + 10 * Числа2.Поле), МЕСЯЦ) <= КОНЕЦПЕРИОДА(&ДатаОкончания, МЕСЯЦ)

УПОРЯДОЧИТЬ ПО
	Поле
Показать
27. ildarovich 7232 18.10.16 16:25 Сейчас в теме
(26) HanterVol, (25) Ovrfox, это уже заявки на победу, подождем еще, возможно, будут еще варианты...
28. Ovrfox 14 18.10.16 16:25 Сейчас в теме
(26) HanterVol,
Выражение
КОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Числа1.Поле + 10 * Числа2.Поле), МЕСЯЦ) < НАЧАЛОПЕРИОДА(&ДатаОкончания, МЕСЯЦ)
ТОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Числа1.Поле + 10 * Числа2.Поле), МЕСЯЦ)
не имеет смысла при ограничении по датам и даже без ограничения нужно включать "Выбрать различные"
29. HanterVol 8 18.10.16 16:28 Сейчас в теме
31. HanterVol 8 18.10.16 16:32 Сейчас в теме
(28) Ovrfox, но хотелось избавиться от "Различные"
30. herfis 408 18.10.16 16:28 Сейчас в теме
Ну, мне как-то понадобилась разбивка и по дням и по периодам одновременно. Вот так делал:
ВЫБРАТЬ
	0 КАК Цифра
ПОМЕСТИТЬ Цифры

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	1

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	2

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	3

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	4

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	5

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	6

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	7

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	8

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	9
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ДниПериода.ДеньПериода КАК ДеньПериода,
	ДниПериода.НачалоСтандартногоПериода,
	ДниПериода.КонецСтандартногоПериода,
	РАЗНОСТЬДАТ(ВЫБОР
			КОГДА ДниПериода.НачалоСтандартногоПериода < &НачалоПериода
				ТОГДА &НачалоПериода
			ИНАЧЕ ДниПериода.НачалоСтандартногоПериода
		КОНЕЦ, КОНЕЦПЕРИОДА(ВЫБОР
				КОГДА ДниПериода.КонецСтандартногоПериода > &КонецПериода
					ТОГДА &КонецПериода
				ИНАЧЕ ДниПериода.КонецСтандартногоПериода
			КОНЕЦ, ДЕНЬ), ДЕНЬ) + 1 КАК КвоДнейСтандартногоПериода
ИЗ
	(ВЫБРАТЬ
		ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня) КАК ДеньПериода,
		ВЫБОР
			КОГДА &Периодичность = "БезПериодов"
				ТОГДА &НачалоПериода
			КОГДА &Периодичность = "День"
				ТОГДА ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня)
			КОГДА &Периодичность = "Неделя"
				ТОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), НЕДЕЛЯ)
			КОГДА &Периодичность = "Декада"
				ТОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), ДЕКАДА)
			КОГДА &Периодичность = "Месяц"
				ТОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), МЕСЯЦ)
			КОГДА &Периодичность = "Квартал"
				ТОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), КВАРТАЛ)
			КОГДА &Периодичность = "Полугодие"
				ТОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), ПОЛУГОДИЕ)
			КОГДА &Периодичность = "Год"
				ТОГДА НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), ГОД)
		КОНЕЦ КАК НачалоСтандартногоПериода,
		ВЫБОР
			КОГДА &Периодичность = "БезПериодов"
				ТОГДА &КонецПериода
			КОГДА &Периодичность = "День"
				ТОГДА ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня)
			КОГДА &Периодичность = "Неделя"
				ТОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), НЕДЕЛЯ)
			КОГДА &Периодичность = "Декада"
				ТОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), ДЕКАДА)
			КОГДА &Периодичность = "Месяц"
				ТОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), МЕСЯЦ)
			КОГДА &Периодичность = "Квартал"
				ТОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), КВАРТАЛ)
			КОГДА &Периодичность = "Полугодие"
				ТОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), ПОЛУГОДИЕ)
			КОГДА &Периодичность = "Год"
				ТОГДА КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, НомераДнейПериода.НомерДня), ГОД)
		КОНЕЦ КАК КонецСтандартногоПериода
	ИЗ
		(ВЫБРАТЬ
			Тысячи.Цифра * 1000 + Сотни.Цифра * 100 + Десятки.Цифра * 10 + Единицы.Цифра КАК НомерДня
		ИЗ
			Цифры КАК Тысячи,
			Цифры КАК Сотни,
			Цифры КАК Десятки,
			Цифры КАК Единицы
		ГДЕ
			Тысячи.Цифра * 1000 + Сотни.Цифра * 100 + Десятки.Цифра * 10 + Единицы.Цифра <= РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ)) КАК НомераДнейПериода) КАК ДниПериода
Показать

Думаю, при необходимости несложно допилить до нужного варианта.
32. ildarovich 7232 18.10.16 16:39 Сейчас в теме
(30) herfis, не вполне подходит, так как тут много возни с первым и последним периодом, а в вашем варианте об этом ничего нет, так что без допиливания не подойдет
33. herfis 408 18.10.16 16:45 Сейчас в теме
(32) ildarovich, Есть, на самом деле. "Возня" отображена в вычислении "КвоДнейСтандартногоПериода". Просто делается по аналогии
ВЫБОР
     КОГДА ДниПериода.НачалоСтандартногоПериода < &НачалоПериода
     ТОГДА &НачалоПериода
     ИНАЧЕ ДниПериода.НачалоСтандартногоПериода
КОНЕЦ

и аналогично для конца периода
34. Ovrfox 14 18.10.16 16:59 Сейчас в теме
(33) herfis, Запрос возвращает не кол-во периодов, а одну запись в день. Чтобы получить периоды - нужно группировать - не самый эффективный метод.
Но как вариант - очень хорош.
35. herfis 408 18.10.16 17:14 Сейчас в теме
(34) Ovrfox, Именно так. Я об этом сразу предупредил. По сути, это просто небольшая модификация получения таблицы дней. Мне нужна была именно такая. Вероятно, именно для периодов возможен более оптимальный вариант. Но без группировок (РАЗЛИЧНЫЕ просто одна из вариаций) в голову ничего не приходит. Тут тоже достаточно добавить РАЗЛИЧНЫЕ и убрать "ДеньПериода" для получения таблицы именно периодов.
36. Ovrfox 14 18.10.16 17:15 Сейчас в теме
(33) herfis, Примерно такой запрос получен по вашим следам
При этом легко видеть, что при замене слова НЕДЕЛЯ на любой другой период запрос останется точно таким же, изменится только протяженность периода
ВЫБРАТЬ 
    Выбор когда ДниПериода.НачалоСтандартногоПериода < &НачалоПериода
    Тогда &НачалоПериода
    Иначе ДниПериода.НачалоСтандартногоПериода Конец  КАК НачалоСтандартногоПериода,
    Выбор когда ДниПериода.КонецСтандартногоПериода > &КонецПериода
    Тогда &КонецПериода
    Иначе ДниПериода.КонецСтандартногоПериода Конец  КАК КонецСтандартногоПериода
ИЗ
    (ВЫБРАТЬ Различные
         НАЧАЛОПЕРИОДА(НомераДнейПериода.НашДень, НЕДЕЛЯ) КАК НачалоСтандартногоПериода,
         КОНЕЦПЕРИОДА(НомераДнейПериода.НашДень, НЕДЕЛЯ) КАК КонецСтандартногоПериода
    ИЗ
        (ВЫБРАТЬ
            ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ,Тысячи.Цифра * 1000 + Сотни.Цифра * 100 + Десятки.Цифра * 10 + Единицы.Цифра) КАК НашДень
        ИЗ
            Цифры КАК Тысячи,
            Цифры КАК Сотни,
            Цифры КАК Десятки,
            Цифры КАК Единицы
        ГДЕ
            Тысячи.Цифра * 1000 + Сотни.Цифра * 100 + Десятки.Цифра * 10 + Единицы.Цифра <= РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ)
        ) КАК НомераДнейПериода
 ) как ДниПериода
  упорядочить по   НачалоСтандартногоПериода
Показать
37. herfis 408 18.10.16 17:19 Сейчас в теме
(36) Ovrfox, Все так. Исходный запрос многословен из-за динамической разбивки по периодам (периодичность выбирает пользователь в параметре СКД).
38. ildarovich 7232 18.10.16 20:36 Сейчас в теме
(33) herfis, извиняюсь, невнимательно посмотрел, но ... теперь увидел, что интервал разворачивается по дням. Это слишком легкий путь. И хотя время выполнения тут не особенно критично, все же зачем делать лишние вычисления? Их будет в 30 раз меньше, чем при перечислении не дней, как в (30) и (36), а периодов, как в (25) и (26). Кроме того, при перечислении дней самым простым способом будет использовании уже записанного в (17) запроса. Без лишних условий:
ВЫБРАТЬ
	0 КАК Х
ПОМЕСТИТЬ Бит

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	1
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ДОБАВИТЬКДАТЕ(&Дата1, ДЕНЬ, Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * (Б5.Х + 2 * (Б6.Х + 2 * (Б7.Х + 2 * (Б8.Х + 2 * Б9.Х))))))))) КАК Х
ПОМЕСТИТЬ Даты
ИЗ
	Бит КАК Б0,
	Бит КАК Б1,
	Бит КАК Б2,
	Бит КАК Б3,
	Бит КАК Б4,
	Бит КАК Б5,
	Бит КАК Б6,
	Бит КАК Б7,
	Бит КАК Б8,
	Бит КАК Б9
ГДЕ
	Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * (Б5.Х + 2 * (Б6.Х + 2 * (Б7.Х + 2 * (Б8.Х + 2 * Б9.Х)))))))) <= РАЗНОСТЬДАТ(&Дата1, &Дата2, ДЕНЬ)
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	МИНИМУМ(Даты.Х) КАК ДатаНачала,
	МАКСИМУМ(Даты.Х) КАК ДатаОкончания
ИЗ
	Даты КАК Даты

СГРУППИРОВАТЬ ПО
	РАЗНОСТЬДАТ(&Дата1, Даты.Х, МЕСЯЦ)
Показать
39. herfis 408 19.10.16 09:24 Сейчас в теме
(38) ildarovich, Согласен.
ЗЫ. В использовании двоичного расчета плюсов не вижу, скорее наоборот, а вот группировка по разности дат - элегантный ход.
40. ildarovich 7232 19.10.16 11:33 Сейчас в теме
(39) herfis, двоичный, десятичный и тому подобное к сути решения не относятся. Можно использовать кому что нравится. Я использовал двоичное основание из-за того, что оно дает самую короткую запись, выраженную в числе строк запроса, раскрытого конструктором. Уж очень длинной выглядит формирование таблицы из десяти цифр. Еще плюсом двоичного основания является минимум лишнего в итоге соединения, из которой затем выбирается нужное число записей, потому что ряд 1-2-4-8-16-64-128 чаще, чем 1-10-100-1000. Есть и минусы и другие методы. Но здесь об этом смысла спорить не вижу.
Сейчас хочу увидеть более короткое чем (25) и (26) решение без развертки по дням.
42. herfis 408 19.10.16 12:40 Сейчас в теме
(40) ildarovich, ИМХО, Orfox победитель.
Он первый предложил оптимальный алгоритм генерации таблицы периодов (без группировок). Оптимальнее вроде некуда. Один простой запрос.
Остальное, включая уточнение границ периодов - вторично.
45. ildarovich 7232 19.10.16 12:52 Сейчас в теме
(42) herfis, хотел еще подождать свежих вариантов, прежде чем победителя определять, не хотелось бы пока точку ставить. Если что, я вознаграждение увеличу.
41. HanterVol 8 19.10.16 12:27 Сейчас в теме
Сделал с другой идеей, но... короче не получилось
ВЫБРАТЬ
	1 КАК Число
ПОМЕСТИТЬ Числа

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	2

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	3

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	4

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	5

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	6

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	7

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	8

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	9

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	0
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	Ед.Число + Дес.Число * 10 + Сот.Число * 100 КАК Номер
ПОМЕСТИТЬ Месяцы
ИЗ
	Числа КАК Ед,
	Числа КАК Дес,
	Числа КАК Сот
ГДЕ
	Ед.Число + Дес.Число * 10 + Сот.Число * 100 <= РАЗНОСТЬДАТ(&Дата1, &Дата2, МЕСЯЦ)
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
	ВложенныйЗапрос.Номер,
	МАКСИМУМ(ВложенныйЗапрос.Дата1) КАК Дата1,
	МИНИМУМ(ВложенныйЗапрос.Дата2) КАК Дата2
ИЗ
	(ВЫБРАТЬ РАЗЛИЧНЫЕ
		Месяцы.Номер КАК Номер,
		&Дата1 КАК Дата1,
		&Дата2 КАК Дата2
	ИЗ
		Месяцы КАК Месяцы
	
	ОБЪЕДИНИТЬ ВСЕ
	
	ВЫБРАТЬ РАЗЛИЧНЫЕ
		Месяцы.Номер,
		НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, МЕСЯЦ, Месяцы.Номер), МЕСЯЦ),
		КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, МЕСЯЦ, Месяцы.Номер), МЕСЯЦ)
	ИЗ
		Месяцы КАК Месяцы) КАК ВложенныйЗапрос

СГРУППИРОВАТЬ ПО
	ВложенныйЗапрос.Номер
Показать
44. ildarovich 7232 19.10.16 12:44 Сейчас в теме
(41) HanterVol, хороший вариант, кое-где вроде бы РАЗЛИЧНЫЕ лишние. Он кажется более "воздушным". Нужно будет еще по числу знаков сравнить.
43. herfis 408 19.10.16 12:42 Сейчас в теме
Было бы соблазнительно сгенерировать таблицу полных периодов и объединить с "краями", но, к сожалению, обработка всех возможных ситуаций в итоге будет выглядеть хуже, а не лучше.
47. ildarovich 7232 24.10.16 17:07 Сейчас в теме
К сожалению, из-за редизайна форума, обещанное вознаграждение до победителя не дошло, останусь должен, сочтемся с Ovrfox при случае.

Для коллекции добавлю свой вариант. Он самый короткий, но не самый простой:
ВЫБРАТЬ
	0 КАК Х
ПОМЕСТИТЬ Бит
ОБЪЕДИНИТЬ
ВЫБРАТЬ
	1
;
ВЫБРАТЬ
	Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * Б5.Х)))) КАК Х
ПОМЕСТИТЬ Периоды
ИЗ
	Бит КАК Б0,
	Бит КАК Б1,
	Бит КАК Б2,
	Бит КАК Б3,
	Бит КАК Б4,
	Бит КАК Б5
ГДЕ
	Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * Б5.Х)))) < РАЗНОСТЬДАТ(&Дата1, &Дата2, МЕСЯЦ)
;
ВЫБРАТЬ
	ЕСТЬNULL(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, МЕСЯЦ, Начала.Х + 1), МЕСЯЦ), &Дата1) КАК ДатаНачала,
	ЕСТЬNULL(КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, МЕСЯЦ, Окончания.Х), МЕСЯЦ), &Дата2) КАК ДатаОкончания
ИЗ
	Периоды КАК Начала
		ПОЛНОЕ СОЕДИНЕНИЕ Периоды КАК Окончания
		ПО (Начала.Х + 1 = Окончания.Х)
Показать



К сожалению, этот вариант не отрабатывает ситуацию отсутствия необходимости разбивки: если Дата1 и Дата2 находятся в одном месяце.
SmArtist; +1 Ответить
50. soulsteps 74 10.03.17 17:17 Сейчас в теме
(47)

Чуточку изменил Ваш запрос:
ВЫБРАТЬ
0 КАК Х
ПОМЕСТИТЬ Бит

ОБЪЕДИНИТЬ

ВЫБРАТЬ
1
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * Б5.Х)))) КАК Х
ПОМЕСТИТЬ Периоды
ИЗ
Бит КАК Б0,
Бит КАК Б1,
Бит КАК Б2,
Бит КАК Б3,
Бит КАК Б4,
Бит КАК Б5
ГДЕ
Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * Б5.Х)))) < РАЗНОСТЬДАТ(&Дата1, &Дата2, МЕСЯЦ)
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
ЕСТЬNULL(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, МЕСЯЦ, Начала.Х + 1), МЕСЯЦ), &Дата1) КАК ДатаНачала,
ЕСТЬNULL(КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, МЕСЯЦ, Окончания.Х), МЕСЯЦ), &Дата2) КАК ДатаОкончания
ИЗ
Периоды КАК Начала
ПОЛНОЕ СОЕДИНЕНИЕ Периоды КАК Окончания
ПО (Начала.Х + 1 = Окончания.Х)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
&Дата1,
&Дата2
ГДЕ
НАЧАЛОПЕРИОДА(&Дата1, МЕСЯЦ) = НАЧАЛОПЕРИОДА(&Дата2, МЕСЯЦ)

УПОРЯДОЧИТЬ ПО
ДатаНачала

Этот вариант не отрабатывает отрабатывает ситуацию отсутствия необходимости разбивки: если Дата1 и Дата2 находятся в одном месяце.
Также, если в тексте запроса МЕСЯЦ -> #Детализация и через СтрЗаменить(...) в тексте запроса заменять #Детализация на МЕСЯЦ, ДЕНЬ, КВАРТАЛ... То можно получить вполне универсальную функцию.
SmArtist; +1 Ответить
48. spenser123 31.10.16 13:01 Сейчас в теме
Я, может, не врубился до конца в тему, но не понимаю чем не устраивает банальные варианты с:
НАЧАЛОПЕРИОДА(Дата,&Периодичность) Как НачалоПериода
КОНЕЦПЕРИОДА(Дата,&Периодичность) Как КонецПериода

?
49. ildarovich 7232 31.10.16 13:50 Сейчас в теме
(48) задача совсем другая: дан интервал, его нужно РАЗБИТЬ на подпериоды. То есть ответом должно быть множество записей - по одной для каждого входящего в интервал подпериода.
Например, 15.08.16 - 30.10.16 разбивается на месяцы так: 15.08.16 - 31.08.16; 1.09.16 - 30.09.16; 1.10.16 - 30.10.16.
soulsteps; +1 Ответить
Оставьте свое сообщение
Вопросы с вознаграждением