|
Имющие(Having). Как реализовать виртуальную таблицу "СрезПоследних". | ☑ | ||
---|---|---|---|---|
0
NikePopov
23.07.15
✎
16:12
|
Добрый день!
Столкнулся с задачей: Есть документ "Заявка", в котором указывается какой контрагент сколько продукции будет потреблять. При проведении документ пишет запись в регистр сведений "АктуальнаяЗаявка"(доступен СрезПоследних). Сделано это потому, что по умолчанию, завтра требуется поставить столько же продукции, сколько поставили вчера(если не было подано новой заявки). Требуется определить, сколько материалов требуется для выпуска продукции за год. Остальные вещи описывать не буду(как устроен справочник "Спецификации", какие дополнительные реквизиты есть), так как к вопросу они не имеют отношения. Сейчас код выглядит так: Пока ТекущаяДата <= ДатаОкончания Цикл Выполняем запрос к регистру(срез последних)... ТекущаяДата = ТекущаяДата + День; КонецЦикла; Такой цикл проходит 365 или 366 раз подряд. Что вызывает 365 или 366 раз запрос, что довольно долго. Пытаюсь составить запрос, в котором можно было бы выполнить аналогичные действия "СрезПоследних", но за один вызов. Имея опыт работы с другими базами данных, запрос бы выглядел так: select dates.date, // Дата из таблицы, которую мы обрабатываем max(requests.customer), // Измерение "Контрагент" регистра "АктуальнаяЗаявка" max(requests.request) // Регистратор регистра "АктуальнаяЗаявка" from dates inner join requests on dates.date >= requests.date group by dates.date having requests.date = max(requests.date) Проблема в том, что в конструкции "ГДЕ" нельзя использовать поля группировка "МАКСИМУМ", а в конструкции "ИМЕЮЩИЕ" нельзя использовать не группированные поля. То есть в языке запросов 1С не может ни в какой части запроса быть выражение "АктуальнаяЗаявка.Период = МАКСИМУМ(АктуальнаяЗаявка.Период)" Кто-нибудь знает способ реализовать вариант как в обычном запросе? |
|||
1
Serginio1
23.07.15
✎
16:17
|
||||
2
Ёпрст
23.07.15
✎
16:17
|
пользуй временную табличку для нахождения максимума и её пихай в имеющие
|
|||
3
NikePopov
23.07.15
✎
16:22
|
(1) У меня обратная ситуация. Я знаю, как написать запрос SQL, а вот как обратно?
(2) Есть идея для запроса? МАКСИМУМ надо взять для МоментВремени, а не для Дата! Потому что регистр по позиции регистратора! А максимум по МоментВремени взять нельзя! Уже пробовал. |
|||
4
Serginio1
23.07.15
✎
16:27
|
(3) Можно использовать прямой запрос.
Можно использовать Top(1) v8: Подзапросы с Выбрать Первые Правда по сравнению с той платформой можно использовать только одно поле. Но в примере вмето (РеализацияТоваровУслугТовары.Ссылка, РеализацияТоваровУслугТовары.НомерСтроки) В нужно использовать просто РеализацияТоваровУслугТовары.НомерСтроки В |
|||
5
Vladal
23.07.15
✎
16:28
|
(3) Есть такая идея. Ниже запрос. Если что лишнего - я просто выкинул шелуху, оставил только основное для понимания.
ВЫБРАТЬ ТоварыПТУ.Номенклатура КАК Номенклатура, ТоварыПТУ.Цена КАК Цена, ТоварыПТУ.Количество КАК Количество, НАЧАЛОПЕРИОДА(ТоварыПТУ.Ссылка.Дата, ДЕНЬ) КАК ДатаГТД ПОМЕСТИТЬ ВТ_ОсновнаяВыборка ИЗ Документ.ПоступлениеТоваровУслуг.Товары КАК ТоварыПТУ ГДЕ ТоварыПТУ.Ссылка.Проведен И ТоварыПТУ.Номенклатура.КодУКТВЭД <> ЗНАЧЕНИЕ(Справочник.КлассификаторУКТВЭД.ПустаяСсылка) ИНДЕКСИРОВАТЬ ПО Номенклатура ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ ПоступлениеТоваровУслугТовары.Номенклатура КАК Номенклатура, МАКСИМУМ(ПоступлениеТоваровУслугТовары.ДатаГТД) КАК ДатаГТД ПОМЕСТИТЬ ВТ_ПоследниеЦены ИЗ ВТ_ОсновнаяВыборка КАК ПоступлениеТоваровУслугТовары СГРУППИРОВАТЬ ПО ПоступлениеТоваровУслугТовары.Номенклатура ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ ВТ_ОсновнаяВыборка.Номенклатура КАК Номенклатура, ВТ_ОсновнаяВыборка.Цена, ВТ_ОсновнаяВыборка.Количество, ВТ_ОсновнаяВыборка.ДатаГТД, ВТ_ПоследниеЦены.ДатаГТД КАК ДатаПоследнейЦены ПОМЕСТИТЬ ВТ_ИтоговаяТаблица ИЗ ВТ_ОсновнаяВыборка КАК ВТ_ОсновнаяВыборка ПОЛНОЕ СОЕДИНЕНИЕ ВТ_ПоследниеЦены КАК ВТ_ПоследниеЦены ПО ВТ_ОсновнаяВыборка.Номенклатура = ВТ_ПоследниеЦены.Номенклатура И ВТ_ОсновнаяВыборка.ДатаГТД = ВТ_ПоследниеЦены.ДатаГТД ПОЛНОЕ СОЕДИНЕНИЕ ВТ_СредниеЦены КАК ВТ_СредниеЦены ПО ВТ_ОсновнаяВыборка.Номенклатура = ВТ_СредниеЦены.Номенклатура ИНДЕКСИРОВАТЬ ПО Номенклатура ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ ВТ_ИтоговаяТаблица.Номенклатура КАК Номенклатура, ВТ_ИтоговаяТаблица.Цена, ВТ_ИтоговаяТаблица.Количество, ВТ_ИтоговаяТаблица.ДатаГТД КАК ДатаГТД, ВТ_ИтоговаяТаблица.ДатаПоследнейЦены ИЗ ВТ_ИтоговаяТаблица КАК ВТ_ИтоговаяТаблица УПОРЯДОЧИТЬ ПО Номенклатура, ДатаГТД |
|||
6
Serginio1
23.07.15
✎
16:29
|
||||
7
Vladal
23.07.15
✎
16:32
|
(3) > У меня обратная ситуация. Я знаю, как написать запрос SQL, а вот как обратно?
Этот запрос к базе 1С или сторонней базе? Если сторонней, то подключайся к той базе по АДО и выполняй свой запрос. А как перевести - можешь и латинские литералы использовать, вроде select - 1С-ный язык запросов их понимает. |
|||
8
NikePopov
23.07.15
✎
16:35
|
(7) У меня все данные в регистре сведений. Внешних данных нет. Я попытался перевести с "языка SQL" на язык запросов 1С, но либо я плохо перевел, либо у 1С не умеет работать с ИМЕЮЩИЕСЯ в полном объеме, как это возможнго с SQL.
(4) (5) (6) Пытаюсь вникнуть. |
|||
9
NikePopov
23.07.15
✎
16:42
|
На простом примере(из головы):
Есть торги. Есть покупатели, есть номенклатуры. Победитель - тот кто предложил максимальную стоимость. Дано: -----------------------------------------| Клиент | Номенклатура | Предложенная цена| -----------------------------------------| Клиент1| Номенклатура1|10 | Клиент2| Номенклатура1|20 | Клиент1| Номенклатура2|30 | Клиент2| Номенклатура2|40 | ------------------------------------------ Задача: запросом определить победителей по номенклатурам. Ответ для SQL: select max(dano.client), dano.nom AS nom , max(dano.price) from dano group bu nom having dano.client = max(dano.client) Результат запроса: -----------------------------------------| Клиент | Номенклатура | Предложенная цена| -----------------------------------------| Клиент2| Номенклатура1|20 | Клиент2| Номенклатура2|40 | ------------------------------------------ Нужен запрос для 1С... |
|||
10
Serginio1
23.07.15
✎
16:47
|
||||
11
DmitrO
23.07.15
✎
16:55
|
(9)А в каком это SQL, в предложении HAVING можно использовать поля по которым не группировали?
Приведите пример с указанием конкретного сервера (языка запросов SQL). :) |
|||
12
itlikbez
23.07.15
✎
17:04
|
(8) 1С прекрасно умеет работать с HAVING. Читайте документацию внимательно.
|
|||
13
Vladal
23.07.15
✎
17:17
|
(8) Чтобы использовать ИМЕЮЩИЕ в запросе, надо это поле сгруппировать.
Пример: "ВЫБРАТЬ | ПартииТоваровНаСкладах.Склад, | ПартииТоваровНаСкладах.Номенклатура, | СУММА(ПартииТоваровНаСкладах.Количество) КАК Количество |ИЗ | РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах | |СГРУППИРОВАТЬ ПО | ПартииТоваровНаСкладах.Номенклатура, | ПартииТоваровНаСкладах.Склад | |ИМЕЮЩИЕ | СУММА(ПартииТоваровНаСкладах.Количество) < 0" |
|||
14
Vladal
23.07.15
✎
17:19
|
(9) выбрать
максимум(dano.client), dano.nom как nom, максимум(dano.price) из dano сортировать по nom имеющие dano.client = максимум(dano.client) так пройдет в твоей базе? |
|||
15
mistеr
23.07.15
✎
17:47
|
(0) Ссылку на "срез последних на каждый день уже дали". Но для твоей задачи
> Требуется определить, сколько материалов требуется для выпуска продукции за год. лучше использовать регистр накопления и не иметь этих проблем. |
|||
16
NikePopov
24.07.15
✎
08:31
|
(14) в конструкции "ИМЕЮЩИЕ" недопустимо использовать поля, не входящие в группировку (для этого примера - "dano.client") (15) (15) Это вопрос архитектуры конфигурации, на которое я повлиять не могу. Я только пишу внешнюю обработку. говорить "надо снимать конфигурацию с поддержки" не имеет смысла. Ведь можно выполнять запрос в цикле на каждый день.
Ну и регистром накопления встает вопрос: кто будет туда писать данные? Заявка - тогда вопрос, до какого периода писать туда данные? На месяц? А если завтра поменяются данные? В общем, в конфигурации сделано довольно разумно. |
|||
17
mistеr
24.07.15
✎
09:01
|
(16) Если конфа на поддержке, тогда другое дело. Я полагал, что архитектура в твоих руках.
> Заявка - тогда вопрос, до какого периода писать туда данные? На месяц? Ну заявка ведь на какой-то период делается? |
|||
18
NikePopov
24.07.15
✎
09:10
|
(17) Нет. Звонит клиент и говорит, что с сегодняшнего дня мне надо 15 шт/день. Потом позвонит через два с половиной месяца скажет, что привози 18 шт/день
|
|||
19
NikePopov
24.07.15
✎
09:11
|
(17) Договор на год. Но заявка будет действовать неопределенный период.
|
|||
20
Simod
24.07.15
✎
10:10
|
(0) Пример запроса получения курса валюты на дату каждого документа выборки:
ВЫБРАТЬ ПоступлениеТоваровУслугТовары.Ссылка.Дата КАК Дата, ПоступлениеТоваровУслугТовары.Номенклатура КАК Номенклатура, ПоступлениеТоваровУслугТовары.Ссылка, ПоступлениеТоваровУслугТовары.Цена, КурсыВалют.Курс, КурсыВалют.Кратность ИЗ Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугТовары ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют ПО (КурсыВалют.Валюта = &Валюта) И (КурсыВалют.Период В (ВЫБРАТЬ ПЕРВЫЕ 1 МАКСИМУМ(Т.Период) ИЗ РегистрСведений.КурсыВалют КАК Т ГДЕ Т.Валюта = &Валюта И Т.Период <= ПоступлениеТоваровУслугТовары.Ссылка.Дата)) |
|||
21
NikePopov
24.07.15
✎
10:17
|
(20) Отличный вариант! Я его уже пробовал, но у меня " МАКСИМУМ(Т.Период)" надо заменить на МАКСИМУМ(Т.МоментВремени) , и тут платформа возмутилась на невозможность сравнения "строк неограниченной длинны и составных значений). Вероятнее всего, Момент времени является "составным значением"(структура Дата+НомерЗаписи). У меня регистр сведений по позиции регистратора (3) , так что использовать дату не совсем корректно. Вероятность ошибки, конечно, довольно мала. Но если вдруг получится, что этим воспользуются, то в результате будет 2 записи на одну дату.
|
|||
22
Simod
24.07.15
✎
10:32
|
(21) Т.е. надо на момент времени каждого документа?
|
|||
23
Simod
24.07.15
✎
10:37
|
(21) Какая периодичность у РС "АктуальнаяЗаявка"?
|
|||
24
Serginio1
24.07.15
✎
10:37
|
(21) Момент времени это Дата+Ссылка. То есть В
(ВЫБРАТЬ последние 1 Т.Период ИЗ РегистрСведений.КурсыВалют КАК Т ГДЕ Т.Валюта = &Валюта И Т.Период <= ПоступлениеТоваровУслугТовары.Ссылка.Дата Сортировать По Т.Период)) Но у регистра сведений нет регистра сведений. И ты можешь получить несколько документов на одну дату. Опять можешь применить выбрать первые или максимум. |
|||
25
NikePopov
24.07.15
✎
10:39
|
(22) Неа. Для каждой даты.
Пример: Мне нужен срез последних на даты: 01.01.2015 00:00:00 02.01.2015 00:00:00 03.01.2015 00:00:00 ... 29.12.2015 00:00:00 30.12.2015 00:00:00 31.12.2015 00:00:00 Возможна ситуация, при которой Есть 2 документа: Документ Заявка №00-00125 от 01.01.2015 15:32:15(была создана первой) Документ Заявка №00-00126 от 01.01.2015 15:32:15(была создана второй) При этом количество продукции на 02.01.2015 00:00:00 надо взять из "Документ Заявка №00-00126 от 01.01.2015 15:32:15", так как именно его выберет срез последних. |
|||
26
NikePopov
24.07.15
✎
10:48
|
(23) По позиции регистратора. Прошу прощения, только заметил сообщение.
|
|||
27
Simod
24.07.15
✎
12:31
|
(26) Тогда можно заменить "Период" на "Регистрато.МоментВремени", но это не есть гуд..
|
|||
28
NikePopov
31.07.15
✎
09:15
|
(27) Нельзя. Уже определились в (21), что вариант сравнения "строк неограниченной длинны и составных значений" недопустимо.
|
|||
29
Serginio1
31.07.15
✎
10:47
|
(28) А какой у регистра курса валют МоментВремени?
Если он и есть то там не нужен максимум. И (КурсыВалют.Регистратор В (ВЫБРАТЬ ПЕРВЫЕ 1 Т.Регистратор ИЗ РегистрСведений.КурсыВалют КАК Т ГДЕ Т.Валюта = &Валюта И Т.Период <= ПоступлениеТоваровУслугТовары.Ссылка.Дата УПОРЯДОЧИТЬ ПО Т.МоментВремени) |
|||
30
Serginio1
31.07.15
✎
11:11
|
Или
УПОРЯДОЧИТЬ ПО Т.Период,Т.Регистратор |
|||
31
kittystark
31.07.15
✎
12:31
|
может поможет ? как пример для анализа
для того, чтобы построить отчет на СКД по оборачиваемости товаров мне нужны были конечные остатки на КАЖДЫЙ день, идти надо не от документа, а от регистра, и обрати внимание какие регистры задействованы для ВТ Движения, он там один, но один раз остатки, второй обороты
|
|||
32
Serginio1
31.07.15
✎
20:16
|
Вернее Выбрать Последние 1
или УПОРЯДОЧИТЬ ПО Т.Период убыв,Т.Регистратор убыв |
|||
33
Aprobator
31.07.15
✎
21:40
|
(0) СКД в помощь. 2 набора данных, один - требуемые даты (с производственного календаря их раз плюнуть получить). Второй - сам срез последних. Ну и связь между наборами по дате. Метода известная и довольно несложная.
|
|||
34
kittystark
01.08.15
✎
08:49
|
(33) да метода известная и один из первых отчетов на СКД по оборачиваемости сделал по ней, но отчет получился тормознутым на больших периодах, то что описано в (31) работает гораздо быстрее, а на выходе результат один и тот же
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |