Помогите решить задачу на СКД с датами и периодами - Отчет

1. progersan 6 07.12.23 18:00 Сейчас в теме
Всем привет!

Конфигурация самописная. 1С на управляемых формах.

Есть справочник Сотрудники. Есть два нужных реквизита типа Дата: ДатаПриема и ДатаУвольнения.
Хотелось бы средствами СКД решить задачу. Но пока не понял как.

Берем период - месяц. Например, Июль.
Нужно отобрать и посчитать всех сотрудников у кого ДатаПриема = ИЮЛЬ, а ДатаУвольнения ИЮЛЬ и АВГУСТ.
Эти данные нужно сгруппировать в колонке, назвать Июль.В идеале, пользователь видит несколько колонок по каждому месяцу. И данные в каждой колонке должны быть посчитаны именно по такому алгоритму.

Я задачу решил по одному месяцу. Т.е. я делаю запрос, когда выбран один месяц ИЮЛЬ (Период), то я беру этот месяц и оперирую им. Посчитать относительно Периода уволенных в данном месяце +1 и посчитать принятых в Периоде....

UPDATE
Коллеги! Всем спасибо, что приняли участие в этом челлендже по работе мозгов ))) я так давно не вспоминал месяца совместно с СКД. Огромное спасибо, что освежили память и подтолкнули в нужному решению. Все решения , приведенные ниже рабочие, особенно с временной таблицей дат! Это монстр! :) Но я решил по наводке мистера RustamZz.
Оно мне показалось более лаконичным.
ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(Сотрудники.датаприем, МЕСЯЦ) КАК МесяцПриема,
    КОЛИЧЕСТВО(Сотрудники.сотрудник) КАК Принято,
    КОЛИЧЕСТВО(Сотрудники1.сотрудник) КАК Уволено
ИЗ
    Сотрудники КАК Сотрудники
        ЛЕВОЕ СОЕДИНЕНИЕ Сотрудники КАК Сотрудники1
        ПО Сотрудники.сотрудник = Сотрудники1.сотрудник
            И (Сотрудники1.датаувольнения МЕЖДУ НАЧАЛОПЕРИОДА(Сотрудники.датаприем, МЕСЯЦ) И КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(Сотрудники.датаприем, МЕСЯЦ, 1), МЕСЯЦ))

СГРУППИРОВАТЬ ПО
    НАЧАЛОПЕРИОДА(Сотрудники.датаприем, МЕСЯЦ)
Показать
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
7. Vinzor 91 07.12.23 20:02 Сейчас в теме
(1) Вам надо получить таблицу периодов с шагом 1 месяц, между &ДатаНачала и &ДатаОкончания, имя поля например Месяц (вид значения 01.07.2023 и т.д.). Это основа.
К ней "левым" будете присоединять справочник по условиям связки периодов с датами приемв и увольнения.
Примерно так
Выбрать 
ВТ_Периоды.Месяц, 
Сотрудники.Сотрудник
Из 
ВТ_Периоды Как ВТ_Периоды
Левое Соединения Сотрудники Как Сотрудники 
По ВТ_Периоды.Месяц = НачалоПериода(Сотрудники.ДатаПриема, месяц) 
И Сотрудники.ДатаУвольнения <> ДатаВремя(1,1,1) 
И НачалоПериода(Сотрудники.ДатаУвольнения, месяц) = ВТ_Периоды.Месяц
И НачалоПериода(Сотрудники.ДатаУвольнения, месяц) <= ДобавитьКДате(ВТ_Периоды.Месяц, месяц, 1)
Показать

Помещай это во временную, потому вынимай считай количество сотрудников по полю "Месяц"

А это полный запрос получения "Месяцев"
ВЫБРАТЬ
	0 КАК Цифра
ПОМЕСТИТЬ ВТЦифры

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

ВЫБРАТЬ
	1

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

ВЫБРАТЬ
	2

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

ВЫБРАТЬ
	3

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

ВЫБРАТЬ
	4

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

ВЫБРАТЬ
	5

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

ВЫБРАТЬ
	6

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

ВЫБРАТЬ
	7

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

ВЫБРАТЬ
	8

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

ВЫБРАТЬ
	9
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(ВЫБОР
					КОГДА &НачалоПериода = ДАТАВРЕМЯ(1, 1, 1)
						ТОГДА ДАТАВРЕМЯ(1980, 1, 1)
					ИНАЧЕ &НачалоПериода
				КОНЕЦ, МЕСЯЦ), МЕСЯЦ, Цифры.Цифра + ЕСТЬNULL(Цифры10.Цифра, 0) * 10 + ЕСТЬNULL(Цифры100.Цифра, 0) * 100 + ЕСТЬNULL(Цифры1000.Цифра, 0) * 1000 + ЕСТЬNULL(Цифры10000.Цифра, 0) * 10000 + ЕСТЬNULL(Цифры100000.Цифра, 0) * 100000), МЕСЯЦ) КАК Период
ПОМЕСТИТЬ ПредставленияПериоды
ИЗ
	ВТЦифры КАК Цифры
		ЛЕВОЕ СОЕДИНЕНИЕ ВТЦифры КАК Цифры10
		ПО (РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &НачалоПериода = ДАТАВРЕМЯ(1, 1, 1)
							ТОГДА ДАТАВРЕМЯ(1980, 1, 1)
						ИНАЧЕ &НачалоПериода
					КОНЕЦ, МЕСЯЦ), НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &ОкончаниеПериода = КОНЕЦПЕРИОДА(ДАТАВРЕМЯ(1, 1, 1), МЕСЯЦ)
							ТОГДА &ОкончаниеИнтервалаПредставленияПериоды
						ИНАЧЕ &ОкончаниеПериода
					КОНЕЦ, МЕСЯЦ), МЕСЯЦ) > 9)
		ЛЕВОЕ СОЕДИНЕНИЕ ВТЦифры КАК Цифры100
		ПО (РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &НачалоПериода = ДАТАВРЕМЯ(1, 1, 1)
							ТОГДА ДАТАВРЕМЯ(1980, 1, 1)
						ИНАЧЕ &НачалоПериода
					КОНЕЦ, МЕСЯЦ), НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &ОкончаниеПериода = КОНЕЦПЕРИОДА(ДАТАВРЕМЯ(1, 1, 1), МЕСЯЦ)
							ТОГДА &ОкончаниеИнтервалаПредставленияПериоды
						ИНАЧЕ &ОкончаниеПериода
					КОНЕЦ, МЕСЯЦ), МЕСЯЦ) > 99)
		ЛЕВОЕ СОЕДИНЕНИЕ ВТЦифры КАК Цифры1000
		ПО (РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &НачалоПериода = ДАТАВРЕМЯ(1, 1, 1)
							ТОГДА ДАТАВРЕМЯ(1980, 1, 1)
						ИНАЧЕ &НачалоПериода
					КОНЕЦ, МЕСЯЦ), НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &ОкончаниеПериода = КОНЕЦПЕРИОДА(ДАТАВРЕМЯ(1, 1, 1), МЕСЯЦ)
							ТОГДА &ОкончаниеИнтервалаПредставленияПериоды
						ИНАЧЕ &ОкончаниеПериода
					КОНЕЦ, МЕСЯЦ), МЕСЯЦ) > 999)
		ЛЕВОЕ СОЕДИНЕНИЕ ВТЦифры КАК Цифры10000
		ПО (РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &НачалоПериода = ДАТАВРЕМЯ(1, 1, 1)
							ТОГДА ДАТАВРЕМЯ(1980, 1, 1)
						ИНАЧЕ &НачалоПериода
					КОНЕЦ, МЕСЯЦ), НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &ОкончаниеПериода = КОНЕЦПЕРИОДА(ДАТАВРЕМЯ(1, 1, 1), МЕСЯЦ)
							ТОГДА &ОкончаниеИнтервалаПредставленияПериоды
						ИНАЧЕ &ОкончаниеПериода
					КОНЕЦ, МЕСЯЦ), МЕСЯЦ) > 9999)
		ЛЕВОЕ СОЕДИНЕНИЕ ВТЦифры КАК Цифры100000
		ПО (РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &НачалоПериода = ДАТАВРЕМЯ(1, 1, 1)
							ТОГДА ДАТАВРЕМЯ(1980, 1, 1)
						ИНАЧЕ &НачалоПериода
					КОНЕЦ, МЕСЯЦ), НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &ОкончаниеПериода = КОНЕЦПЕРИОДА(ДАТАВРЕМЯ(1, 1, 1), МЕСЯЦ)
							ТОГДА &ОкончаниеИнтервалаПредставленияПериоды
						ИНАЧЕ &ОкончаниеПериода
					КОНЕЦ, МЕСЯЦ), МЕСЯЦ) > 99999)
ГДЕ
	НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(ВЫБОР
						КОГДА &НачалоПериода = ДАТАВРЕМЯ(1, 1, 1)
							ТОГДА ДАТАВРЕМЯ(1980, 1, 1)
						ИНАЧЕ &НачалоПериода
					КОНЕЦ, МЕСЯЦ), МЕСЯЦ, Цифры.Цифра + ЕСТЬNULL(Цифры10.Цифра, 0) * 10 + ЕСТЬNULL(Цифры100.Цифра, 0) * 100 + ЕСТЬNULL(Цифры1000.Цифра, 0) * 1000 + ЕСТЬNULL(Цифры10000.Цифра, 0) * 10000 + ЕСТЬNULL(Цифры100000.Цифра, 0) * 100000), МЕСЯЦ) МЕЖДУ ВЫБОР
			КОГДА &НачалоПериода = ДАТАВРЕМЯ(1, 1, 1)
				ТОГДА ДАТАВРЕМЯ(1980, 1, 1)
			ИНАЧЕ &НачалоПериода
		КОНЕЦ И ВЫБОР
			КОГДА &ОкончаниеПериода = КОНЕЦПЕРИОДА(ДАТАВРЕМЯ(1, 1, 1), МЕСЯЦ)
				ТОГДА &ОкончаниеИнтервалаПредставленияПериоды
			ИНАЧЕ &ОкончаниеПериода
		КОНЕЦ
;

////////////////////////////////////////////////////////////­////////////////////
УНИЧТОЖИТЬ ВТЦифры
Показать
8. user1880116 07.12.23 21:10 Сейчас в теме
(7)
И НачалоПериода(Сотрудники.ДатаУвольнения, месяц) = ВТ_Периоды.Месяц
И НачалоПериода(Сотрудники.ДатаУвольнения, месяц) <= ДобавитьКДате(ВТ_Периоды.Месяц, месяц, 1)

Всегда ложь
9. Vinzor 91 07.12.23 21:16 Сейчас в теме
(8) С чего бы?
Или надо просто месяц без года?
10. user1880116 07.12.23 21:31 Сейчас в теме
(9)
чего бы

Точно, не всегда ложь. Оно просто неправльно.
Читаем условие:
Нужно отобрать и посчитать всех сотрудников у кого ДатаПриема = ИЮЛЬ, а ДатаУвольнения ИЮЛЬ и АВГУСТ.
Эти данные нужно сгруппировать в колонке, назвать Июль


Пример: уволен 10 августа. Должен попасть в июль.

ВТ_Периоды = июнь: 1 августа = 1 июня И 1 августа <= 1 июля. Строки нет.
ВТ_Периоды = июль: 1 августа = 1 июля И 1 августа <= 1 августа. Строки нет.
ВТ_Периоды = август: 1 августа = 1 августа И 1 августа <= 1 сентября. Строка есть.
ВТ_Периоды = сентябрь: 1 августа = 1 сентября И 1 августа <= 1 октября. Строки нет.
11. Vinzor 91 07.12.23 21:39 Сейчас в теме
(10) Опечатался малость. Без Конструктора в самом инфостарте писать код жутко неудобно.
Речь идёт об этом
И НачалоПериода(Сотрудники.ДатаПриёма, месяц) = ВТ_Периоды.Месяц
И НачалоПериода(Сотрудники.ДатаУвольнения, месяц) <= ДобавитьКДате(ВТ_Периоды.Месяц, месяц, 1)

Вы или просто внимательный человек, или пробовали код и наткнулись на эту мелкую ошибку :)
2. ImHunter 315 07.12.23 18:28 Сейчас в теме
(1) Можно подумать в сторону запроса, где Сотрудники с1 соединяются сами с собой с2 по условию с1.Сылка=с2.Ссылка и с2.ДатаУвольнения>с1.ДатаПриема.
А можно вроде сделать такое соединение и СКД-шным механизмом Объединение. И там в условиях связи подобное условие реализовать.
3. progersan 6 07.12.23 18:38 Сейчас в теме
(2) спасибо! Но эту мысль я уже реализовал. Он у меня работает в режиме одного периода, например, Месяц - который выбирает пользователь в отчете. Условия немного сложнее, чем вы описали. Вот как сейчас выглядит запрос
Вопрос в том как реализовать периоды в отчете? Периодом должен быть Месяц. Примем отчет должен каждый период отталкиваться от Месяца (смотреть от каждого месяца уволенных за 2 месяца, принятых за 1 - относительно группировки отчета так скажем)
Прикрепленные файлы:
4. user1880116 07.12.23 18:45 Сейчас в теме
Просто считай количество в колонке как сумму выбора: если дата увольнения попадает в месяц даты приема или в следующий месяц, тогда 1, иначе 0. Группируй по месяцу даты приема
6. RustamZz 07.12.23 18:56 Сейчас в теме
(4)
ВЫБРАТЬ
	НАЧАЛОПЕРИОДА(Сотрудники.датаприем, МЕСЯЦ) КАК МесяцПриема,
	КОЛИЧЕСТВО(Сотрудники.сотрудник) КАК Принято,
	КОЛИЧЕСТВО(Сотрудники1.сотрудник) КАК Уволено
ИЗ
	Сотрудники КАК Сотрудники
		ЛЕВОЕ СОЕДИНЕНИЕ Сотрудники КАК Сотрудники1
		ПО Сотрудники.сотрудник = Сотрудники1.сотрудник
			И (Сотрудники1.датаувольнения МЕЖДУ НАЧАЛОПЕРИОДА(Сотрудники.датаприем, МЕСЯЦ) И КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(Сотрудники.датаприем, МЕСЯЦ, 1), МЕСЯЦ))

СГРУППИРОВАТЬ ПО
	НАЧАЛОПЕРИОДА(Сотрудники.датаприем, МЕСЯЦ)
Показать
5. ImHunter 315 07.12.23 18:46 Сейчас в теме
(3) Не особо в картинки вник. Может РАЗНОСТЬДАТ(...) в помощь?
Так получите таблицу вида Сотрудник, ПериодПриема, ПериодУвольнения, ПроработалМес. И потом в СКД как хотите, так и группируйте и агрегируйте.
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот