|
Запрос к периодическому регистру сведений | ☑ | ||
---|---|---|---|---|
0
first_may
12.07.17
✎
20:36
|
Добрый день.
В базе есть периодический регистр сведений с измерением «Контрагент» и ресурсом «Менеджер». Подскажите пож, как с помощью запроса собрать данные по периодам, в течение которых у контрагента был тот или иной менеджер? |
|||
1
Лефмихалыч
12.07.17
✎
20:47
|
Выбрать
Период ИЗ регистрСведений.ПериодическийРегистрСведений ГДЕ Контрагент = &Контрагент и Менеджер = &ОпределенныйМенеджер |
|||
2
first_may
12.07.17
✎
21:25
|
(1) так получается только дата.. а как получить таблицу
из колонок С По Контрагент Менеджер |
|||
3
Cyberhawk
12.07.17
✎
21:35
|
Кастуй Ildarovich в ветку ))
|
|||
4
first_may
12.07.17
✎
21:45
|
(3) почему он? :)
|
|||
5
Cyberhawk
12.07.17
✎
22:23
|
(4) Славится умением (и пониманием) в запросах мутить всякую магию
|
|||
6
kumena
12.07.17
✎
22:30
|
(5) есть и другие, которые как минимум не хуже пишут.
|
|||
7
first_may
12.07.17
✎
22:33
|
Хотелось бы научиться :)
|
|||
8
Лефмихалыч
12.07.17
✎
22:37
|
Тогда (1) во временную, потом ещё одну временную с менеджер<>, потом ту с этой соединить по условию период<период и выбрать максимум периодов, и результат ещё раз соединить с самой первой временной.
Поищи 'срез последних на каждую дату' - это один и самых распространенных шаблонов проектирования у 1сников |
|||
9
SleepyHead
гуру
13.07.17
✎
07:31
|
Если запросы не знаешь, выгружай в таблицу значений результат простого запроса, в виде
дата начала, менеджер, контрагент, сортируй по дате начала, добавляй колонку "дата окончания", пробегайся по строкам таблицы и проставляй дату окончания. Не буду писать, как это сделать, догадайся. |
|||
10
KishMish
13.07.17
✎
07:43
|
я так понял, есть данные на каждую дату
Дата Контрагент Менеджер Надо сделать эту таблицу периодами? ДатаНач ДатаКон КОнтрагент Менеджер Если да то вот этот кусок кода это делает //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ в_Графики.Сотрудник, в_Графики.ДатаВыхода, в_Графики.ОтработаноЧасов - ЕСТЬNULL(вт_УказанныеРанее.ОтработаноЧасов, 0) КАК ОтработаноЧасов ПОМЕСТИТЬ вт_Данные ИЗ в_Графики КАК в_Графики ЛЕВОЕ СОЕДИНЕНИЕ вт_УказанныеРанее КАК вт_УказанныеРанее ПО в_Графики.Сотрудник = вт_УказанныеРанее.Сотрудник И в_Графики.ДатаВыхода = вт_УказанныеРанее.ДатаВыхода ГДЕ в_Графики.ОтработаноЧасов - ЕСТЬNULL(вт_УказанныеРанее.ОтработаноЧасов, 0) > 0 ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ вт_Данные.ДатаВыхода КАК ДатаВыхода, вт_Данные.Сотрудник, вт_ДанныеП.ДатаВыхода ЕСТЬ NULL КАК Начало, вт_ДанныеС.ДатаВыхода ЕСТЬ NULL КАК Конец ПОМЕСТИТЬ вт_ПоискГраниц ИЗ вт_Данные КАК вт_Данные ПОЛНОЕ СОЕДИНЕНИЕ вт_Данные КАК вт_ДанныеС ПО (ДОБАВИТЬКДАТЕ(вт_Данные.ДатаВыхода, ДЕНЬ, 1) = вт_ДанныеС.ДатаВыхода) И вт_Данные.Сотрудник = вт_ДанныеС.Сотрудник ПОЛНОЕ СОЕДИНЕНИЕ вт_Данные КАК вт_ДанныеП ПО (ДОБАВИТЬКДАТЕ(вт_Данные.ДатаВыхода, ДЕНЬ, -1) = вт_ДанныеП.ДатаВыхода) И вт_Данные.Сотрудник = вт_ДанныеП.Сотрудник ГДЕ НЕ вт_Данные.Сотрудник ЕСТЬ NULL И (вт_ДанныеП.ДатаВыхода ЕСТЬ NULL ИЛИ вт_ДанныеС.ДатаВыхода ЕСТЬ NULL) ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ вт_Начало.Сотрудник КАК Сотрудник, вт_Начало.ДатаВыхода КАК ДатаНачала, МИНИМУМ(вт_Конец.ДатаВыхода) КАК ДатаОкончания ПОМЕСТИТЬ вт_ГотовыеПериоды ИЗ вт_ПоискГраниц КАК вт_Начало ВНУТРЕННЕЕ СОЕДИНЕНИЕ вт_ПоискГраниц КАК вт_Конец ПО (вт_Начало.Начало) И (вт_Конец.Конец) И вт_Начало.Сотрудник = вт_Конец.Сотрудник ГДЕ вт_Конец.ДатаВыхода >= вт_Начало.ДатаВыхода СГРУППИРОВАТЬ ПО вт_Начало.Сотрудник, вт_Начало.ДатаВыхода ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ вт_ГотовыеПериоды.Сотрудник КАК Сотрудник, вт_ГотовыеПериоды.ДатаНачала, вт_ГотовыеПериоды.ДатаОкончания, СУММА(1) КАК День, СУММА(вт_Данные.ОтработаноЧасов) КАК ОтработаноЧасов ИЗ вт_ГотовыеПериоды КАК вт_ГотовыеПериоды ЛЕВОЕ СОЕДИНЕНИЕ вт_Данные КАК вт_Данные ПО вт_ГотовыеПериоды.Сотрудник = вт_Данные.Сотрудник И (вт_Данные.ДатаВыхода МЕЖДУ вт_ГотовыеПериоды.ДатаНачала И вт_ГотовыеПериоды.ДатаОкончания) СГРУППИРОВАТЬ ПО вт_ГотовыеПериоды.Сотрудник, вт_ГотовыеПериоды.ДатаНачала, вт_ГотовыеПериоды.ДатаОкончания УПОРЯДОЧИТЬ ПО Сотрудник, вт_ГотовыеПериоды.ДатаНачала |
|||
11
KishMish
13.07.17
✎
07:46
|
+(10) если есть вопросы тексту запроса задавай
Основная тема такая Ищем Границы периодов - вт_ПоискГраниц Потом получаем периоды - вт_ГотовыеПериоды А потом соединяем вт_ГотовыеПериоды с данными |
|||
12
first_may
13.07.17
✎
10:08
|
(11) СПСАИБО!!!
|
|||
13
first_may
13.07.17
✎
11:21
|
(11) а вот тут
ВЫБРАТЬ вт_Данные.ДатаВыхода КАК ДатаВыхода, вт_Данные.Сотрудник, вт_ДанныеП.ДатаВыхода ЕСТЬ NULL КАК Начало, вт_ДанныеС.ДатаВыхода ЕСТЬ NULL КАК Конец ПОМЕСТИТЬ вт_ПоискГраниц ИЗ вт_Данные КАК вт_Данные ПОЛНОЕ СОЕДИНЕНИЕ вт_Данные КАК вт_ДанныеС ПО (ДОБАВИТЬКДАТЕ(вт_Данные.ДатаВыхода, ДЕНЬ, 1) = вт_ДанныеС.ДатаВыхода) И вт_Данные.Сотрудник = вт_ДанныеС.Сотрудник ПОЛНОЕ СОЕДИНЕНИЕ вт_Данные КАК вт_ДанныеП ПО (ДОБАВИТЬКДАТЕ(вт_Данные.ДатаВыхода, ДЕНЬ, -1) = вт_ДанныеП.ДатаВыхода) И вт_Данные.Сотрудник = вт_ДанныеП.Сотрудник ГДЕ НЕ вт_Данные.Сотрудник ЕСТЬ NULL И (вт_ДанныеП.ДатаВыхода ЕСТЬ NULL ИЛИ вт_ДанныеС.ДатаВыхода ЕСТЬ NULL) ; почему именно (ДОБАВИТЬКДАТЕ(вт_Данные.ДатаВыхода, ДЕНЬ, 1) = вт_ДанныеС.ДатаВыхода) ?? |
|||
14
KishMish
13.07.17
✎
12:38
|
(13) таблица вт_Данные должна содержать данные на каждый день интерисуемого периода без пропусков.
То есть в твоем случае тебе в таблице Данные нужно сделать так чтобы было Период Контрагент Менеджер 01.01.2017 Контрагент1 Менеджер1 02.01.2017 Контрагент1 Менеджер1 03.01.2017 Контрагент1 Менеджер1 03.01.2017 Контрагент1 Менеджер2 04.01.2017 Контрагент1 Менеджер2 05.01.2017 Контрагент1 Менеджер2 ... 01.01.2017 Контрагент2 Менеджер3 02.01.2017 Контрагент2 Менеджер3 03.01.2017 Контрагент2 Менеджер3 03.01.2017 Контрагент2 Менеджер3 04.01.2017 Контрагент2 Менеджер2 05.01.2017 Контрагент2 Менеджер2 ... и так далее. то есть то есть состояние на каждый день, для каждой совокупности Контрагент Менеджер. Ты сможешь ее получить? и далее при получении вт_ПоискГраниц код твой будет такой ВЫБРАТЬ вт_Данные.Период КАК Период, вт_Данные.Контрагент, вт_Данные.Менеджер, вт_ДанныеП.Период ЕСТЬ NULL КАК Начало, вт_ДанныеС.Период ЕСТЬ NULL КАК Конец ПОМЕСТИТЬ вт_ПоискГраниц ИЗ вт_Данные КАК вт_Данные ПОЛНОЕ СОЕДИНЕНИЕ вт_Данные КАК вт_ДанныеС ПО (ДОБАВИТЬКДАТЕ(вт_Данные.Период, ДЕНЬ, 1) = вт_ДанныеС.Период) И вт_Данные.Контрагент = вт_ДанныеС.Контрагент И вт_Данные.Менеджер = вт_ДанныеС.Менеджер //тут вообще столько условий сколько у тебя ключевых полей ПОЛНОЕ СОЕДИНЕНИЕ вт_Данные КАК вт_ДанныеП ПО (ДОБАВИТЬКДАТЕ(вт_Данные.Период, ДЕНЬ, -1) = вт_ДанныеП.Период) И вт_Данные.Контрагент = вт_ДанныеП.Контрагент И вт_Данные.Менеджер = вт_ДанныеП.Менеджер |
|||
15
KishMish
13.07.17
✎
12:39
|
+(14)
ГДЕ НЕ вт_Данные.Контрагент ЕСТЬ NULL И (вт_ДанныеП.ДатаВыхода ЕСТЬ NULL ИЛИ вт_ДанныеС.ДатаВыхода ЕСТЬ NULL) |
|||
16
KishMish
13.07.17
✎
12:42
|
(13) и ответ на почему именно
(ДОБАВИТЬКДАТЕ(вт_Данные.ДатаВыхода, ДЕНЬ, 1) = вт_ДанныеС.ДатаВыхода) я соеденяю таблицу со следующим днем (ДОБАВИТЬКДАТЕ(вт_Данные.ДатаВыхода, ДЕНЬ, 1) = вт_ДанныеС.ДатаВыхода) и с предыдущим ПО (ДОБАВИТЬКДАТЕ(вт_Данные.Период, ДЕНЬ, -1) = вт_ДанныеП.Период) |
|||
17
first_may
13.07.17
✎
12:58
|
(16) а у меня нет следующего дня, так как есть например запись
01.05.2011 .. 03.08.2011 .. |
|||
18
first_may
13.07.17
✎
13:02
|
(14) "то есть состояние на каждый день" - такого нет, есть большой промежуток между датами..
|
|||
19
KishMish
13.07.17
✎
13:04
|
(17) сделай из нее таблицу на все даты.
как делать? найти в инете как запросом получить курсы валют на каждый день. и сделай по тому типу свою например http://catalog.mista.ru/public/337365/ там используется ПроизводсвенныйКалендарь. Если у тебя нет календаря, то тогда тебе нужно сформировать таблицу дат. это запрос тоже можно в инете найти. |
|||
20
Diman000
13.07.17
✎
13:18
|
В детали сабжа я не вникал, но навскидку в (9) не самый плохой вариант предложен.
Сервер SQL мощная штука, смекалистая и многое умеет оптимизировать. Я про MS, с остальными в промышленном масштабе не работал. Но задачи сложные для запросов частенько лучше решать кодом на сервере приложений, чем придумывать или искать хитрые решения, которые могут прилично нагрузить сервер СУБД. |
|||
21
1dvd
13.07.17
✎
13:20
|
(20) +1
|
|||
22
first_may
13.07.17
✎
14:12
|
(20) надо одним запросом :), без таблиц.
|
|||
23
1dvd
13.07.17
✎
14:13
|
(22) кому надо?
|
|||
24
Naf2017
13.07.17
✎
14:16
|
||||
25
Diman000
13.07.17
✎
15:07
|
(22)
Присоединяюсь к вопросу (23) Кому надо? Есть процедура или функция которая обрабатывает именно результат запроса? Тогда ее надо немного подправить, это недолго. Есть динамический список в который хочется зафигачить этот запрос? Тогда этого делать нельзя, это прилично затормозит форму. Лучше переписать на статическую таблицу. Но это долго. Но надо. Ну и третий вариант, тебе поставили задачу выдать именно РезультатЗапроса? В таком случае надо включить свою голову и обосновать постановщику почему это плохо. Могут быть и еще варианты, мне было бы интересно их услышать. |
|||
26
KishMish
13.07.17
✎
15:23
|
(25) метод решения зависит от предполагаемого количества строк в результате. При большом количество строк в выходной таблице обработка строк в цикле будет намного дольше чем запросом.
|
|||
27
Diman000
13.07.17
✎
15:24
|
(26) Согласен, хороший аргумент.
|
|||
28
first_may
13.07.17
✎
15:25
|
Для саморазвития надо сделать только с помощью запроса :).
|
|||
29
Diman000
14.07.17
✎
01:03
|
(28) Если все так серьезно, то загляните сразу в профайлер SQL. Для саморазвития очень полезно)
|
|||
30
first_may
14.07.17
✎
09:33
|
(10) добрый день..
тут ВЫБРАТЬ в_Графики.Сотрудник, в_Графики.ДатаВыхода, в_Графики.ОтработаноЧасов - ЕСТЬNULL(вт_УказанныеРанее.ОтработаноЧасов, 0) КАК ОтработаноЧасов ПОМЕСТИТЬ вт_Данные ИЗ в_Графики КАК в_Графики ЛЕВОЕ СОЕДИНЕНИЕ вт_УказанныеРанее КАК вт_УказанныеРанее ПО в_Графики.Сотрудник = вт_УказанныеРанее.Сотрудник И в_Графики.ДатаВыхода = вт_УказанныеРанее.ДатаВыхода ГДЕ в_Графики.ОтработаноЧасов - ЕСТЬNULL(вт_УказанныеРанее.ОтработаноЧасов, 0) > 0 я понимаю, что в_Графики - это календарь дней, то есть 01.01.., 02.01.. и тд.. а вт_УказанныеРанее - ? |
|||
31
first_may
14.07.17
✎
11:08
|
Спасибо всем. Разобрался.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |