Имя: Пароль:
1C
1С v8
Несколько небольших запросов и вопросы по ним
0 suvolod
 
06.12.11
10:28
Доброе время суток всему народу.
Встретил в одном из учебников запрос вот такого содержания:

Запрос.Текст =
   "ВЫБРАТЬ РАЗЛИЧНЫЕ
   |    РасходнаяНакладнаяСписокТоваров.Ссылка
   |ИЗ
   |    Документ.РасходнаяНакладная.СписокТоваров КАК РасходнаяНакладнаяСписокТоваров
   |ГДЕ
   |    РасходнаяНакладнаяСписокТоваров.Ссылка.Проведен = Истина
   |    И РасходнаяНакладнаяСписокТоваров.Ссылка.Дата МЕЖДУ &НачПериода И &КонПериода
   |
   |УПОРЯДОЧИТЬ ПО
   |    РасходнаяНакладнаяСписокТоваров.Ссылка.МоментВремени";

... мне не понятен его сакральный смысл. Почему-бы тот-же самый запрос не реализовать проще:

Запрос.Текст =
"ВЫБРАТЬ
|    РасходнаяНакладная.Ссылка
|ИЗ
|    Документ.РасходнаяНакладная КАК РасходнаяНакладная
|ГДЕ
|    РасходнаяНакладная.Проведен = ИСТИНА
|    И РасходнаяНакладная.Дата МЕЖДУ &ДатаНач И &ДатаКон
|
|УПОРЯДОЧИТЬ ПО
|    РасходнаяНакладная.МоментВремени";


... мой вариант мне кажется проще и оптимальнее, т.к. в первом варианте по сути выбирается то-же самое, но из результата выкидываются дубли... но, может, я что-то упустил?
1 YF
 
06.12.11
10:30
(0) Твой вариант отберет и документы с пустой табличной частью
2 suvolod
 
06.12.11
10:36
Точно, проглядел.. Но тогда получается, что выбрать гарантированно непустую ТЗ, надо поступать именно так - т.е. формировать кучу дублирующих записей, а потом все их отбрасывать? Как-то через ж... получается, в запросе выполняется куча бесполезной работы
3 Defender aka LINN
 
06.12.11
10:38
(2) А тебе один фиг делать соединение с ТЧ надо будет.
4 Ненавижу 1С
 
гуру
06.12.11
10:38
"ВЫБРАТЬ
   |    РасходнаяНакладнаяСписокТоваров.Ссылка
   |ИЗ
   |    Документ.РасходнаяНакладная.СписокТоваров КАК РасходнаяНакладнаяСписокТоваров
   |ГДЕ
   |    РасходнаяНакладнаяСписокТоваров.Ссылка.Проведен = Истина
   |    И РасходнаяНакладнаяСписокТоваров.Ссылка.Дата МЕЖДУ &НачПериода И &КонПериода
   |СГРУППИРОВАТЬ ПО РасходнаяНакладнаяСписокТоваров.Ссылка
   |ИМЕЮЩИЕ МИНИМУМ(РасходнаяНакладнаяСписокТоваров.НомерСтроки)=1
   |УПОРЯДОЧИТЬ ПО
   |    РасходнаяНакладнаяСписокТоваров.Ссылка.МоментВремени"
5 YF
 
06.12.11
10:40
(4) А принципиальная разница есть?

В (0) больше записей в исходной таблице отбор (т.е. Различные)
В (4) Минимум - тоже занимает некоторое время ...
6 Defender aka LINN
 
06.12.11
10:41
(4) ИМЕЮЩИЕ МИНИМУМ(РасходнаяНакладнаяСписокТоваров.НомерСтроки)=1
Это что за лютый, леденящий душу звиздец? :)
7 Ненавижу 1С
 
гуру
06.12.11
10:42
(6) че те не так то?
(5) ну кто ж спорил бы
8 Defender aka LINN
 
06.12.11
10:44
(7) Какбе, эта строчка может служить только для обогрева серверной, и то не сильно поможет :)
Выкинуть ее нафиг.
9 suvolod
 
06.12.11
10:45
Спасибо, с этим запросом все прояснилось :) И еще небольшой вопрос. Есть функция вида:

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

//дальнейший код функции
КонецФункциии

в дальнейшем эта таблица соединяется еще с двумя, формируя записи вида
ВсеПоляВремТаб + ДетальныеОстаткиПоРегиструБухгалтерии + СводныеОстаткиПоРегиструБухгалтерии

Меня беспокоит опять-же оптимальность. Ну ладно, Номенклатура,Количество и некоторые другие поля используются ниже по коду достаточно интенсивно, по каждой из них формируется проводка. Но часть полей (СуммаПоДокументу, Покупатель) используются один-единственный раз в заключительной проводке вида:

Если Успех Тогда
       Выборка.Сбросить();
       Выборка.Выбрать();
       
       Движение = НаборЗаписей.Добавить();
       Движение.СчетДт = ПланыСчетов.Управленческий.Покупатели;
       Движение.СчетКт = ПланыСчетов.Управленческий.ПрибылиУбытки;
       Движение.Период = Запрос.Дата;
       Движение.Сумма = СуммаПоДокументу;
       Движение.Содержание = "всего продано (сумма товаров)";
       Движение.СубконтоДт[ПланыВидовХарактеристик.ВидыСубконто.Контрагенты] = Запрос.Покупатель;
       Движение.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконто.Подразделения] = Запрос.Подразделение;
       Движение.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконто.ВидыНоменклатуры] = Перечисления.ВидыНоменклатуры.Товар;    
КонецЕсли;

Не проще-ли было их не вставлять в запрос, а просто получить из аргумента функции? (ДокСсылка.Покупатель, ДокСсылка.СуммаПоДокументу)
10 Ненавижу 1С
 
гуру
06.12.11
10:45
(8) если строчек нет в ТЧ, то МИНИМУМ(РасходнаяНакладнаяСписокТоваров.НомерСтроки) будет давать NULL
11 Defender aka LINN
 
06.12.11
10:46
ДокСсылка.Покупатель - за это ногами бить надо. Это запрос, который считывает ВСЕ реквизиты объекта, кроме табличных частей.
12 Defender aka LINN
 
06.12.11
10:47
(10) Не будет. Т.к. в таблице "Документ.РасходнаяНакладная.СписокТоваров" хранятся строки ТЧ.
13 Ненавижу 1С
 
гуру
06.12.11
10:48
(12) и чему же он тогда будет равен интересно знать? ))
14 suvolod
 
06.12.11
10:49
А насколько это неоптимально? Я про то, что на формирование доп. колонок и записей по ним тоже требует ресурсов. Может, в самом начале объявить две переменные:

Покупатель=ДокСсылка.Покупатель;
СуммаПоДокументу=ДокСсылка.СуммаПоДокументу

. и потом обращаться уже непосредственно к ним?
15 Defender aka LINN
 
06.12.11
10:54
(13) Ничему не будет равен. Строк-то нет :)
(14) От того, что ты их в другое место уберешь, платформа себя вести иначе не станет
16 suvolod
 
06.12.11
11:01
Уважаемы Defender aka LINN, можно чуть подробнее в чем моя ошибка? Мои размышления: В документе пять реквизитов: Дата, Номер, Подразделение, СуммаПоДокументу, Покупатель. Получается, чтобы "вытащить" в функцию два два поля, надо выполнить дважды выполнить запрос к реквизитам и считать 2*5=10 записей.

Но разве это тяжелее по вычислениям, чем в едином запросе построить две добавочные колонки по этим полям и заполнить их для всех записей запроса? Например, если в документе будет тч на 20 строк, то это 2*20=40 записей.
17 hhhh
 
06.12.11
11:04
(16) СГРУППИРОВАТЬ - это свернуть, оно работает очень медленно, это будет не 2*40 иа 2*4000.
18 hhhh
 
06.12.11
11:05
(16) и достаточно было

|СГРУППИРОВАТЬ ПО
       |    РасходнаяНакладнаяСписокТоваров.Ссылка,
       |    РасходнаяНакладнаяСписокТоваров.Номенклатура

нафига ты 8 группировок написал?
19 Defender aka LINN
 
06.12.11
11:06
(16) Чего это дважды? Запрос выполняется один раз и считывает только нужные данные.
А реквизитов сегодня 5, а завтра 55 пять. Или предлагаешь писать код по-разному везде, чтобы потом его весело и увлекательно было сопровождать?
20 Ненавижу 1С
 
гуру
06.12.11
11:07
(12) а точно, там явно соединять шапку с ТЧ надо ((
21 suvolod
 
06.12.11
11:08
так сгруппировал не не я. Учебный курс 1С "Конфигурирование платформы 1С предприятие 8.2"
22 suvolod
 
06.12.11
11:08
... методичка этого курса
23 suvolod
 
06.12.11
11:09
но ведь если не сгруппируешь, то по этим полям будут пустые записи. А запросом надо получать по ним данные. Короче, понятно что все-таки придется делать так, как в методичке
24 suvolod
 
06.12.11
11:18
Ну и последний небольшой вопрос. При формировании запросов (особенно соединений страниц) удобно пользоваться конструктором. Но стоит только вставить в запрос строку про менеджер временных таблиц - и конструктор такой запрос не распознает.
По сути, приходиться заново писать конструктором такой-же запрос, соединять его с другими таблицами, а потом в сгенерированном коде вычищать запрос по ВремТаб, заменяя его менеджером.

Мне непонятно, это конструктор не поддерживает менеджер временных таблиц или я не разобрался как его цеплять к конструктору?
25 suvolod
 
06.12.11
11:19
... соединений таблиц, опечатка :)
26 Defender aka LINN
 
06.12.11
11:20
(24) Там кнопка есть специальная
27 suvolod
 
06.12.11
11:20
... шутка или серьезно существует :)? Где?
28 suvolod
 
06.12.11
11:23
я уже вроде весь конструктор облазил. Есть кнопка "создать вложенный запрос", но ведь это не то.
29 rs_trade
 
06.12.11
11:46
(24) закладка Дополнительно. Там ВТ
30 Defender aka LINN
 
06.12.11
12:46
(28) Следующая.
31 Kashemir
 
06.12.11
12:59
(28) С ВТ в конструкторе может возникнут лажа только при использовании производных полей ВТ, определяемой вне данного фрагмента запроса (ибо на данной будет неясен тип полей ВТ, ранее помещенной в менеджер), однако эту проблему можно решить предварительной явной типизацией.

А так смотри (29), для создания ВТ в пределах текущего запроса и (30) для описания ВТ, должной уже существовать в менеджере либо передаваемой в виде параметра ТЗ с типизированными колонками.
32 Kashemir
 
06.12.11
13:05
+(31) Оба запроса рабочие и по сути тождественные (если конечно номенклатуру передавать).

Однако первый запрос конструктор съест нормально, а на второй поругается  в силу озвученных выше причин.


// ЗАПРОС 1
ВЫБРАТЬ
   ВЫРАЗИТЬ(ВТСНоменклатурой.Ссылка КАК Справочник.Номенклатура) КАК Номенклатура
ПОМЕСТИТЬ МояВТ
ИЗ
   Номенклатура КАК ВТСНоменклатурой
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   МояВТ.Номенклатура.Наименование
ИЗ
   МояВТ КАК МояВТ



// ЗАПРОС 2



ВЫБРАТЬ
   ВТСНоменклатурой.Ссылка  КАК Номенклатура
ПОМЕСТИТЬ МояВТ
ИЗ
   Номенклатура КАК ВТСНоменклатурой
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   МояВТ.Номенклатура.Наименование
ИЗ
   МояВТ КАК МояВТ
33 suvolod
 
06.12.11
15:19
....только сейчас увидел, что на мой вопрос отписались. Нет, про вкладку Дополнительно я знаю, но я имел ввиду другое:

МенеджерВт=Новый МенеджерВременныхТаблиц;
   Запрос = Новый Запрос;
   Запрос.МенеджерВременныхТаблиц=МенеджерВТ;
   Запрос.Текст =
       "ВЫБРАТЬ
       |    РасходнаяНакладнаяСписокТоваров.Номенклатура,
       |    РасходнаяНакладнаяСписокТоваров.Количество
       |ПОМЕСТИТЬ ВремТаб
       |ИЗ
       |    Документ.РасходнаяНакладная.СписокТоваров КАК РасходнаяНакладнаяСписокТоваров
       |ГДЕ
       |    РасходнаяНакладнаяСписокТоваров.Ссылка = &Ссылка";

       
   //далее идет какой-то код, не связанный с запросом. После чего надо вновь
   //обратиться к времтаб ("подцепить" ее конструктором запроса)
   
   Запрос = Новый Запрос;
   Запрос.МенеджерВременныхТаблиц=МенеджерВТ;
   Запрос.Текст = ... //здесь хочу соединить ВремТаб с другими таблицами
   
   //но в этом втором запросе констуктор уже ничего не знает про ВремТаб,
   //сформированную выше, хотя я вроде прямо указываю в параметре нового
   //запроса Запрос.МенеджерВременныхТаблиц=МенеджерВТ;
34 suvolod
 
06.12.11
15:26
т.е. когда я создаю конструктором пакет запросов, то запрос2 видит времтаб из запроса1. Хотелось бы что-то подобное сотворить, когда между запросом1 и запросом2 стоит некоторый код. Но ведь они все-равно связаны менеджером временных таблиц, значит конструктор теоретически может понять, какая таблица лежит в менеджере. Примерно так-же, как нижележащая функция знает о функции, определенной выше. Хотя, возможно, я просто размечтался и в этот функционал в платформе не реализован
35 Kashemir
 
06.12.11
16:43
(34) Менеджер временных таблицы используется в момент выполнения кода, конструктор используется в конфигураторе. Откуда ж ему знать что будет лежать по факту в менеджере ?
36 Kashemir
 
06.12.11
16:47
(34) Опять же - конструктор ничего не будет иметь против использования таблиц, которые "могут" быть в менеджере, до тех пор пока не станешь обращаться к производным полей , при том что конструктор не знает их типов.


Т.е. конструктор съест молча вот такое обращение

   МенеджерВт=Новый МенеджерВременныхТаблиц;
   Запрос = Новый Запрос;
   Запрос.МенеджерВременныхТаблиц=МенеджерВТ;
   Запрос.Текст =
       "ВЫБРАТЬ
       |    РасходнаяНакладнаяСписокТоваров.Номенклатура,
       |    РасходнаяНакладнаяСписокТоваров.Количество
       |ПОМЕСТИТЬ ВремТаб
       |ИЗ
       |    Документ.РасходнаяНакладная.СписокТоваров КАК РасходнаяНакладнаяСписокТоваров
       |ГДЕ
       |    РасходнаяНакладнаяСписокТоваров.Ссылка = &Ссылка";



   
   Запрос = Новый Запрос;
   Запрос.МенеджерВременныхТаблиц=МенеджерВТ;
   Запрос.Текст = "ВЫБРАТЬ
                  |    ВремТаб.Номенклатура,
                  |    ВремТаб.Количество
                  |ИЗ
                  |    ВремТаб КАК ВремТаб";

Но такого не поймет ...

   МенеджерВт=Новый МенеджерВременныхТаблиц;
   Запрос = Новый Запрос;
   Запрос.МенеджерВременныхТаблиц=МенеджерВТ;
   Запрос.Текст =
       "ВЫБРАТЬ
       |    РасходнаяНакладнаяСписокТоваров.Номенклатура,
       |    РасходнаяНакладнаяСписокТоваров.Количество
       |ПОМЕСТИТЬ ВремТаб
       |ИЗ
       |    Документ.РасходнаяНакладная.СписокТоваров КАК РасходнаяНакладнаяСписокТоваров
       |ГДЕ
       |    РасходнаяНакладнаяСписокТоваров.Ссылка = &Ссылка";

       
   //далее идет какой-то код, не связанный с запросом. После чего надо вновь

   //обратиться к времтаб ("подцепить" ее конструктором запроса)

   
   Запрос = Новый Запрос;
   Запрос.МенеджерВременныхТаблиц=МенеджерВТ;
   Запрос.Текст = "ВЫБРАТЬ
                  |    ВремТаб.Номенклатура.Ссылка,
                  |    ВремТаб.Количество
                  |ИЗ
                  |    ВремТаб КАК ВремТаб";