Имя: Пароль:
1C
1С v8
Что быстрее работает - ГДЕ или соединение?
0 suvolod
 
23.02.13
11:45
Пусть есть две таблицы:
1-я содержит поле номенклатура, период.
2-я содержит поля номенклатура, цена, период.

мне нужно соединить их в одну таблицу по полям Номенклатура + Период, однако вторая таблица строиться на основе ФИЗИЧЕСКОЙ таблицы ЦеныНоменклатуры, и должна содержать только записи по одному типу цен. Возник вопрос: как правильней отфильтровать записи по регистру цен?

1-й способ: это просто применить условие ...ГДЕ при выборке данных второй таблицы. Т.е., как я понимаю - сперва будут выбраны все записи по Регистру цен, после чего записи по ненужному типу цен будут отброшены.

2-й способ: в 1-ю таблицу добавить поле &ТипЦен и соединить обе таблица уже по трем полям: Номенклатура+Период+ТипЦен. Дело в том, что я не совсем понимаю, как будет происходить выборка данных в этом случае.. может, она будет быстрее и не потребует чтения всей таблицы цен?
1 suvolod
 
23.02.13
11:46
на всякий случай: такая задача оптимизации возникла при необходимости решения учетной задачки способом "срез последних на каждую дату"
2 GANR
 
23.02.13
12:01
(0) запросы в ветку
3 suvolod
 
23.02.13
12:03
Пока сделал так (задача) - выбрать поступления товаров за заданный период + прицепить к ним колонку розничных цен:

ВЫБРАТЬ
   ПартииТоваровНаСкладах.Номенклатура КАК Номенклатура,
   ПартииТоваровНаСкладах.Склад КАК Склад,
   ПартииТоваровНаСкладах.Регистратор.Контрагент КАК Поставщик,
   ПартииТоваровНаСкладах.Регистратор КАК Регистратор,
   НАЧАЛОПЕРИОДА(ПартииТоваровНаСкладах.Период, ДЕНЬ) КАК Период,
   СУММА(ПартииТоваровНаСкладах.Количество) КАК Количество,
   СУММА(ПартииТоваровНаСкладах.Стоимость) КАК Стоимость
ПОМЕСТИТЬ ЗапросПоПартиям
ИЗ
   РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах
ГДЕ
   ПартииТоваровНаСкладах.Период МЕЖДУ &Дата1 И &Дата2
   И ПартииТоваровНаСкладах.Активность = ИСТИНА
   И ПартииТоваровНаСкладах.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
   И ПартииТоваровНаСкладах.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг

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

ИНДЕКСИРОВАТЬ ПО
   Номенклатура,
   Период
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   ВложенныйЗапросПартииСПериодом.Номенклатура,
   ВложенныйЗапросПартииСПериодом.Склад,
   ВложенныйЗапросПартииСПериодом.Поставщик,
   ВложенныйЗапросПартииСПериодом.Регистратор,
   ВложенныйЗапросПартииСПериодом.Количество,
   ВложенныйЗапросПартииСПериодом.Стоимость,
   ВложенныйЗапросПартииСПериодом.Период,
   isnull(ЦеныНоменклатуры.Цена,0) КАК Цена
ИЗ
   (ВЫБРАТЬ
       ЗапросПоПартиям.Номенклатура КАК Номенклатура,
       ЗапросПоПартиям.Склад КАК Склад,
       ЗапросПоПартиям.Поставщик КАК Поставщик,
       ЗапросПоПартиям.Регистратор КАК Регистратор,
       ЗапросПоПартиям.Количество КАК Количество,
       ЗапросПоПартиям.Стоимость КАК Стоимость,
       МАКСИМУМ(ЦеныНоменклатуры.Период) КАК Период,
       &ТипЦен КАК ТипЦен
   ИЗ
       ЗапросПоПартиям КАК ЗапросПоПартиям
           ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
           ПО ЗапросПоПартиям.Номенклатура = ЦеныНоменклатуры.Номенклатура
               И ЗапросПоПартиям.Период >= ЦеныНоменклатуры.Период
   
   СГРУППИРОВАТЬ ПО
       ЗапросПоПартиям.Номенклатура,
       ЗапросПоПартиям.Склад,
       ЗапросПоПартиям.Поставщик,
       ЗапросПоПартиям.Регистратор,
       ЗапросПоПартиям.Количество,
       ЗапросПоПартиям.Стоимость) КАК ВложенныйЗапросПартииСПериодом
       ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
       ПО ВложенныйЗапросПартииСПериодом.Номенклатура = ЦеныНоменклатуры.Номенклатура
           И ВложенныйЗапросПартииСПериодом.Период = ЦеныНоменклатуры.Период
           И ВложенныйЗапросПартииСПериодом.ТипЦен = ЦеныНоменклатуры.ТипЦен
4 МихаилМ
 
23.02.13
12:06
одинаково
для субд используюмых 1с
v8: Где указывать условие в запросе когда есть связи
5 H A D G E H O G s
 
23.02.13
12:08
(3) Пофиг.
Главное, ты выбрал первым запросом нужное из Партий, этого достаточно.
А то я уж сразу возбудился, как увидел Вложенный и Партии в нем. Но потом присмотрелся.
6 suvolod
 
23.02.13
12:09
(4)уже что-то.. спасибо. Тогда наверное буду все-таки соедиенением таблиц, т.к. в противном случае придется выборку цен делать вложенным запросом (иначе если я вставлю условие ГДЕ В результирующий запрос, у меня отсеются строки, по которым никогда не было розничных цен)
7 suvolod
 
23.02.13
12:11
заодно задам еще один вопрос:
в классическом примере решения задачи "срез последних на каждую дату" предлагается дважды обращаться к физической таблице регистра цен - сначала по условию выбора максимального периода из минимально возможного периода

ВЫБРАТЬ
....
МАКСИМУМ(ЦеныНоменклатуры.Период) КАК Период
...
И ЗапросПоПартиям.Период >= ЦеныНоменклатуры.Период

Затем по условию равенства периода
И ВложенныйЗапросПартииСПериодом.ТипЦен = ЦеныНоменклатуры.ТипЦен

А разве не правильнее/быстрее было-бы не дважды делать выборку данных из физической таблицы регистра цен, а сперва сделать срез последних на начало выбираемых данных, + через объединение добавить новые записи за весь выбираемый отчетом период.
8 suvolod
 
23.02.13
12:18
(7)... чуть подробнее что я предполагаю:
1. Делаю срез последних - сразу с отбором в параметрах вирт. таблицы по номенклатуре, типу цен.
2. Делаю выборку данных из физ. таблицы регистра по записям, которые были добавлены за период [Дата1, Дата2] - с фильтацией неподходящих записей по ГДЕ
3. Объединяю эти две таблицы и затем уже от полученной результирующей таблице ищу максимум по условию
И ЗапросПоПартиям.Период >= ЦеныНоменклатуры.Период
9 МихаилМ
 
23.02.13
12:20
(7)
для 1с 8.2 все равно fullcscan.
для 8.3 - хратинся таблица срезов как остатки.

почитайте про декларативность запросов.
10 suvolod
 
23.02.13
12:21
(9). Получается, СрезПоследних в 8.2 все равно неявно прочитает всю таблицу цен. Я правильно понял?
11 МихаилМ
 
23.02.13
12:25
(10)
нет.
я неправильно написал. может  задействоваться индекс.

извиняюсь.
12 МихаилМ
 
23.02.13
12:27
+(11)
но индекс будет сканироваться
13 suvolod
 
23.02.13
12:30
Спасибо, а покритикуйте тогда еще один доп. способ оптимизации: прочитать всю таблицу цен, выбрать из нее поля Номенклатура, Цена, Период, поместить во ВремТаб, проиндексировать поля Номенклатура + Период, сразу сделать отбор по ГДЕ на нужный тип цен и номенклатуру. И затем в "классическом" способе решения задачи использовать уже эту частично отфильтрованную таблицу - вместо повторного способа чтения всей физ. таблиц.
14 suvolod
 
23.02.13
12:31
(13).. куча опечаток в конце. Читайте как "- вместо повторного чтения всей физической таблицы цен"
15 МихаилМ
 
23.02.13
12:37
(12)
что такое
"классическом" способе

предположить конечно можно.
но будте конкретней.
16 МихаилМ
 
23.02.13
12:39
+(15)
этот форум будут читать малосведущие.
не ленитесь приводить ссылки
на "КЛАССИЧЕСКИЕ" для ВАС  понятия.
17 suvolod
 
23.02.13
13:05
прошу прощения,  описан здесь: Книга знаний: Срез последних на каждую дату в запросе. Называется "способ непосредственно в запросе"
18 suvolod
 
23.02.13
13:08
как предварительные выводы: если я цены выберу как СрезПоследних на ДатаНач + добью их новыми записями с ДатаНач по ДатаКон, проиндексирую результат, помещу во ВремТаб, и далее буду работать с этой таблицей вместо повторного чтения физической - как минимум медленнее запрос от этого не станет?
19 suvolod
 
23.02.13
17:30
Как окончательные выводы: тестировал на рабочей базе с разными периодами выборки данных. "Классический" запрос всегда отрабатывает быстрее ~ 20-30%. Получается, мое предположение из (18) - неверное. Причем обнаружил странную закономерность: мой запрос из (3), построенный по классическому варианту, отрабатывает быстрее, если в запросе убрать индексирование по полям Номенклатура + Период.
20 Fragster
 
гуру
23.02.13
17:32
(19) а сколько у тебя строк во временной таблице?
21 suvolod
 
23.02.13
17:33
(19). Запрос из (3), оказывается, я приводил как раз без индексирования этих полей. Чтобы было понятнее - о чем говорю - я тестировал запрос с индексированием полей во времтаб, т.е. начало этого запроса было такое:
ВЫБРАТЬ
   ПартииТоваровНаСкладах.Номенклатура КАК Номенклатура,
   ПартииТоваровНаСкладах.Склад КАК Склад,
   ПартииТоваровНаСкладах.Регистратор.Контрагент КАК Поставщик,
   ПартииТоваровНаСкладах.Регистратор КАК Регистратор,
   НАЧАЛОПЕРИОДА(ПартииТоваровНаСкладах.Период, ДЕНЬ) КАК Период,
   СУММА(ПартииТоваровНаСкладах.Количество) КАК Количество,
   СУММА(ПартииТоваровНаСкладах.Стоимость) КАК Стоимость
ПОМЕСТИТЬ ЗапросПоПартиям
ИЗ
   РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах
ГДЕ
   ПартииТоваровНаСкладах.Период МЕЖДУ &Дата1 И &Дата2
   И ПартииТоваровНаСкладах.Активность = ИСТИНА
   И ПартииТоваровНаСкладах.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
   И ПартииТоваровНаСкладах.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг

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

ИНДЕКСИРОВАТЬ ПО
   Номенклатура,
   Период
;
22 suvolod
 
23.02.13
17:36
(20) Примерно 30.000
23 H A D G E H O G s
 
23.02.13
20:01
Где ты видел путь назад?
Очнись, нам уже не вернуться!

Заменить
ПартииТоваровНаСкладах.Регистратор.Контрагент КАК Поставщик,
на

ВЫРАЗИТЬ(ПартииТоваровНаСкладах.Регистратор как Документ.ПоступлениеТоваровУслуг).Контрагент КАК Поставщик,
24 фобка
 
23.02.13
20:49
всё не читал, "где" быстрее чем "джоин"