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

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

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

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

Boulala

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

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

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

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


kilelena

Для оптимизации:
1. Убрать соединение в подзапросом. Формируем две временные таблицы, их соединяем (индексируем поля, по которым будем соединять)
2. В выборке из Документ.ПоступлениеТоваровИУслуг отсутствует условие по организации. Добавляем это условие.

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

saleksvik

1. Убираем соединение с подзапросом. Помещаем результат подзапроса во временную таблицу "ЛимитыКредиторскойЗадолженности".
2. Индексируем временную таблицу по полям, по которым будет проводиться соединение.
3. Параметр "Организация" перемещаем в параметры виртуальной таблицы.
4. Убираем обращение к полям через точку в условии, явно выбирая нужное поле: "ДоговорСПодрядчиком", "ДоговорСПоставщиком".

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

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

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

adamx

Во внутреннем запросе организация задана жестко в условии, поэтому строки

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

теряют смысл.

GreenFox

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

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

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

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


Два самых основных изменения - вынесение выборки по лимитам во временную таблицу с индексацией по полям соединения с таблицей документа ПТиУ и Добавление в соединение условия на равность организаций документа и лимита - иначе при наличии в регистре записей по нескольким организациям у нас бы получилось декартово соединение и продублировались строки. И с точки зрения учета сравнение суммы документа с организацией№1 с лимитами для тогоже контрагента и договора но для организации№2 смысла не имеет.
В сравнении используется функция ЕстьNULL потому что лимита для данной организации по контрагенту и договру может не быть, соответственно соединение даст в поле сумма значение NULL а сравнение с NULL в результате даст  NULL, что в даном условии не может быть.

max_x_X

Из второй таблицы просто выберутся все поля удовлетворяющие условию, не обязательно их явно задавать.

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



michael2k

по запросам - я пас... (((

mzelensky

Вы бы хоть писали для какой конфы этот запрос делался...сидеть создавать все документы, реквизиты, регистры как-то уж совсем времени нет (к тому же называются они через одно место (не видел, чтобы реквизит документа назывался просто "Сумма"...обычно в типовых пишут "СуммаДокумента". Аналогично и реквизит "Договор"))!

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


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

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


1) Вложенный запрос я перенес во временную таблицу
2) Из выбираемых полей (первого запроса) убрал поле "организация", т.к. оно нигде не используется, а следовательно тянуть лишние данные нет смысла
3) На все числовые поля наложил дополниельные проверки на "NULL"

SVGLVV

На мой взгляд, в запросе не все логично. Меня смутило следующее:
1)Из таблицы "ЛимитыКредиторскойЗадолженности" отбираются записи только по одной организации, а из " ПоступлениеТоваровИУслуг " – по всем организациям. Наверное, логичнее или установить отбор по организации и в документе " ПоступлениеТоваровИУслуг ", или отменить отбор по организации в " ЛимитыКредиторскойЗадолженности " и при соединении таблиц добавить условие " И ПоступлениеТоваровИУслуг .Организация = ЛимитыКредиторскойЗадолженности .Организация".
2) При группировке таблицы "ЛимитыКредиторскойЗадолженности" суммируются лимиты для разных типов задолженности (долгосрочная, краткосрочная). И сумма документа сравнивается именно с суммой лимитов.

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


ВЫБРАТЬ
    ПоступлениеТоваровИУслуг.Ссылка,
    ПоступлениеТоваровИУслуг.Номер,
    ПоступлениеТоваровИУслуг.Договор,
    ПоступлениеТоваровИУслуг.Контрагент,
    ПоступлениеТоваровИУслуг.Организация,
    ПоступлениеТоваровИУслуг.Сумма,
    ПоступлениеТоваровИУслуг.Дата
ПОМЕСТИТЬ Т1
ИЗ
    Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг

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

Andrefan

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

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

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

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

Комментарии:
1. Вместо вложенного запроса создана временная таблица для более быстрой работы, добавлены индексы для контрагента и договора, чтобы в больших информационных базах поиск осуществлялся быстрее. При соединении таблицы вставлена проверка на NULL для ресурса Сумма регистра сведения, на случай если в данном регистре регистратором не является документ Поступление.

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

Поиск