Форум 1С
Программистам, бухгалтерам, администраторам, пользователям
Задай вопрос - получи решение проблемы
28 мар 2024, 20:00

Вторник. Вопрос 5

Автор mixqn, 12 мар 2013, 00:51

0 Пользователей и 1 гость просматривают эту тему.

Efa

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

Необходимо в связях добавить Организацию, а для регистра отбор по видам договоров, такой же как для документа

alex-pro

Перенести условия в виртуальную таблицу, если есть такая возможность.
Вместо сложенного запроса использовать Временные таблицы и проиндексировать поля связей.

Smile

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


Одной из основных причин не оптимальной работы запросов является соединения с подзапросами, поэтому лучше делать соединения со временными таблицами. Можно добавить индексацию временной таблицы, так как первое соединение идет по контрагенту:
    "|ИНДЕКСИРОВАТЬ ПО
     |   Контрагент"


savichevae

ВЫБРАТЬ
   ЛимитыКредиторскойЗадолженности.Организация КАК Организация,
   ЛимитыКредиторскойЗадолженности.Контрагент КАК Контрагент,
   ЛимитыКредиторскойЗадолженности.Договор КАК Договор,
   СУММА(ЛимитыКредиторскойЗадолженности.Сумма) КАК Сумма
ПОМЕСТИТЬ  ЛимитыЗадолженности
ИЗ
   РегистрСведений.ЛимитыКредиторскойЗадолженности КАК ЛимитыКредиторскойЗадолженности
ГДЕ
   ЛимитыКредиторскойЗадолженности.Организация = &Организация
       
   СГРУППИРОВАТЬ ПО
   ЛимитыКредиторскойЗадолженности.Организация,
   ЛимитыКредиторскойЗадолженности.Контрагент,
   ЛимитыКредиторскойЗадолженности.Договор
;
/////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
    ПоступлениеТоваровИУслуг.Ссылка,
    ПоступлениеТоваровИУслуг.Номер,
    ПоступлениеТоваровИУслуг.Договор,
    ПоступлениеТоваровИУслуг.Контрагент,
    ПоступлениеТоваровИУслуг.Организация,
    ПоступлениеТоваровИУслуг.Сумма,
    ПоступлениеТоваровИУслуг.Дата
ПОМЕСТИТЬ Поступления
ИЗ
    Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг
ГДЕ
    ПоступлениеТоваровИУслуг.Договор.ДоговорСПодрядчиком = ИСТИНА
    ИЛИ ПоступлениеТоваровИУслуг.Договор.ДоговорСПоставщиком = ИСТИНА
;
/////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ПоступлениеТоваровИУслуг.Ссылка,
    ПоступлениеТоваровИУслуг.Номер,
    ПоступлениеТоваровИУслуг.Договор,
    ПоступлениеТоваровИУслуг.Контрагент,
    ПоступлениеТоваровИУслуг.Организация,
    ПоступлениеТоваровИУслуг.Сумма,
    ПоступлениеТоваровИУслуг.Дата
ИЗ 
    Поступления КАК ПоступлениеТоваровИУслуг
ЛЕВОЕ СОЕДИНЕНИЕ
    ЛимитыЗадолженности КАК ЛимитыКредиторскойЗадолженности
ПО ПоступлениеТоваровИУслуг.Контрагент = ЛимитыКредиторскойЗадолженности.Контрагент
            И ПоступлениеТоваровИУслуг.Договор = ЛимитыКредиторскойЗадолженности.Договор
ГДЕ
    ПоступлениеТоваровИУслуг.Сумма < &МинимальнаяСуммаЗадолженности
            ИЛИ ПоступлениеТоваровИУслуг.Сумма < ЛимитыКредиторскойЗадолженности.Сумма




Т.о. мы избавились от вложенного запроса, что влияет на производительность, а так же при отборе по документов поступлений сразу наложили условия на договор контрагента, что отсеет сразу ненужные данные.

faig

Не нужное соединение с регистрам сведений

PaulMc

ЦитироватьВашему вниманию предлагается запрос. Произведите его оптимизацию и поясните свои действия.
Примечание таблица РегистрСведений.ЛимитыКредиторскойЗадолженности имеет следующие измерения:

Организация
Контрагент
Договор
ТипЗадолженности (долгосрочная, краткосрочная)

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


Из вложенного запроса убрать поле Организация и добавить условие по параметру Организация во внешний запрос. связывать запросы по организации не будем.
Во вложенный запрос для ограничения размера выборки стоит добавить минимальную сумму задолженности и убрать условие из внешнего. нам достаточно один отрезать всё что больше минимума.

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


Вариант 2:
Сначала выберем лимиты, сразу ограничив выборку условиями, их должно быть немного по сравнению с документами. Полученные лимиты соединим с документами:

Код (Пакетный запрос) Выделить
        ВЫБРАТЬ
            ЛимитыКредиторскойЗадолженности.Контрагент КАК Контрагент,
            ЛимитыКредиторскойЗадолженности.Договор КАК Договор,
            СУММА(ЛимитыКредиторскойЗадолженности.Сумма) КАК Сумма
        ПОМЕСТИТЬ Лимиты
        ИЗ
            РегистрСведений.ЛимитыКредиторскойЗадолженности КАК ЛимитыКредиторскойЗадолженности
        ГДЕ
            ЛимитыКредиторскойЗадолженности.Организация = &Организация
        СГРУППИРОВАТЬ ПО
            ЛимитыКредиторскойЗадолженности.Контрагент,
            ЛимитыКредиторскойЗадолженности.Договор
        ИМЕЮЩИЕ
            СУММА(ЛимитыКредиторскойЗадолженности.Сумма) < &МинимальнаяСуммаЗадолженности
            ) КАК ЛимитыКредиторскойЗадолженности
;

////////////////////////////////////////////////////////////////////////////////

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


Вложенные запросы - зло. можно напороться на жесткую цикличность (многократное выполнение вложенного запроса равное количеству строк внешнего), а пакетные вери гуд :befhbt:
хотя немного больше потребуется той же памяти, но скорость работы в разы быстрее за счет уменьшения числа декартового произведения. и читать и дебажить пакетные запросы легче, понятнее и приятнее <_< Рекомендую! B)

kitaets

ВЫБРАТЬ
    ПоступлениеТоваровИУслуг.Ссылка,
    ПоступлениеТоваровИУслуг.Номер,
    ПоступлениеТоваровИУслуг.Договор,
    ПоступлениеТоваровИУслуг.Контрагент,
    ПоступлениеТоваровИУслуг.Организация,
    ПоступлениеТоваровИУслуг.Сумма,
    ПоступлениеТоваровИУслуг.Дата
ИЗ
    Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг
СГРУППИРОВАТЬ ПО
    ПоступлениеТоваровИУслуг.Договор,
    ПоступлениеТоваровИУслуг.Контрагент,
    ПоступлениеТоваровИУслуг.Организация,
    ПоступлениеТоваровИУслуг.Ссылка,
    ПоступлениеТоваровИУслуг.Номер,
    ПоступлениеТоваровИУслуг.Дата,
    СУММА(ЛимитыКредиторскойЗадолженности.Сумма) КАК Задолженность

ЛЕВОЕ СОЕДИНЕНИЕ ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг
    ПО ПоступлениеТоваровИУслуг.Организация =   
       ЛимитыКредиторскойЗадолженности.Организация
И      ПоступлениеТоваровИУслуг.Контрагент =
       ЛимитыКредиторскойЗадолженности.Контрагент
И      ПоступлениеТоваровИУслуг.Договор =
       ЛимитыКредиторскойЗадолженности.Договор           
ГДЕ
    (ПоступлениеТоваровИУслуг.Сумма < &МинимальнаяСуммаЗадолженности
            ИЛИ ПоступлениеТоваровИУслуг.Сумма < ЛимитыКредиторскойЗадолженности.Сумма)
   

vlad___2011___

Внешне все красиво.

Из выборки по регистру убрал контрагента
(предполагая что Контрагент = Договор.Владелец)

и

добавил условие по виду договора

Т.е. уменьшаем объем выборки и сокращаем кол-во
условий в соединении:

ВЫБРАТЬ
    Договор, СУММА(Сумма) КАК Сумма
ИЗ
    РегистрСведений.ЛимитыКредиторскойЗадолженности
ГДЕ
    Организация = &Организация   И
    (Договор.ДоговорСПодрядчиком  ИЛИ  Договор.ДоговорСПоставщиком)
СГРУППИРОВАТЬ ПО
    Договор

Соответственно условие соединения:

ПО
    ПоступлениеТоваровИУслуг.Договор = ЛимитыКредиторскойЗадолженности.Договор
   

Выборку по ПТУ м.б. и переделал бы в подзапрос, но если бы был заранее уверен
что других видов договоров (не пост и не подр) у нас в базе большинство. А так
оставляем как есть.

headmade

1.   При написании запросов не следует использовать соединения с подзапросами т.к. в этом случае возникает вероятность того что СУБД выберет неправильный план выполнения запроса. Поэтому вложенный запрос для регистра сведений ЛимитыКредиторскойЗадолженности необходимо перенести во временную таблицу.
2.   Для уменьшения кол-ва соединяемых полей (на условия к таблице ПоступлениеТоваровИУслуг) выносим таблицу ПоступлениеТоваровИУслуг во временную таблицу.
3.   Индексируем поля временных таблиц, по которым производится соединение.
Итоговый запрос имеет вид:

ВЫБРАТЬ
   ЛимитыКредиторскойЗадолженности.Организация КАК Организация,
   ЛимитыКредиторскойЗадолженности.Контрагент КАК Контрагент,
   ЛимитыКредиторскойЗадолженности.Договор КАК Договор,
   СУММА(ЛимитыКредиторскойЗадолженности.Сумма) КАК Сумма
ПОМЕСТИТЬ ВТ_ЛимитыКредиторскойЗадолженности
ИЗ
   РегистрСведений.ЛимитыКредиторскойЗадолженности КАК ЛимитыКредиторскойЗадолженности
ГДЕ
   ЛимитыКредиторскойЗадолженности.Организация = &Организация

СГРУППИРОВАТЬ ПО
   ЛимитыКредиторскойЗадолженности.Организация,
   ЛимитыКредиторскойЗадолженности.Контрагент,
   ЛимитыКредиторскойЗадолженности.Договор

ИНДЕКСИРОВАТЬ ПО
   Контрагент,
   Договор
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   ПоступлениеТоваровИУслуг.Ссылка,
   ПоступлениеТоваровИУслуг.Номер,
   ПоступлениеТоваровИУслуг.Договор КАК Договор,
   ПоступлениеТоваровИУслуг.Контрагент КАК Контрагент,
   ПоступлениеТоваровИУслуг.Организация,
   ПоступлениеТоваровИУслуг.Сумма,
   ПоступлениеТоваровИУслуг.Дата
ПОМЕСТИТЬ ВТ_ПоступлениеТоваровИУслуг
ИЗ
   Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг
ГДЕ
   (ПоступлениеТоваровИУслуг.Договор.ДоговорСПодрядчиком = ИСТИНА
         ИЛИ ПоступлениеТоваровИУслуг.Договор.ДоговорСПоставщиком = ИСТИНА)

ИНДЕКСИРОВАТЬ ПО
   Контрагент,
   Договор
;

crs

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


В запросе не нужно делать вложенный запрос по регистру сведений ЛимитыКредиторскойЗадолженности: это приводит к тому, что выбираются все записи регистра. Оптимизированный запрос выбирает только те записи, по которым оформлены документы ПоступлениеТоваровИУслуг. Также если, реквизит имеет тип Будево не обязательно писать "Истина".

Теги:
Рейтинг@Mail.ru

Поиск