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

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

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

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

trad_

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

ps Следует обратить внимание на то, что:
- при отсутствии соответствующих записей в регистре,
выражение СУММА(ЛимитыКредиторскойЗадолженности.Сумма) может не иметь значения, то есть быть NULL.
Сравнение с отсутствующим значением всегда Ложь.

- регистр отбирается по организации, а документы ПТиУ не отбираются.
Поэтому регистр в запросе будет "работать" только для части документов. Для другой части сумма лимита будет null.

Исправлять не стал, так как такое "поведение" заложено в исходном запросе.

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

Evgeny

запрос 1 : выделить таблицу ПТУ в во временную сделать отбор по организации
запрос 2 : во второй соединить временную с РС.ЛимитыКредиторскойЗадолженности, сделать левое соединение по Контрагенту и Договору, ограничить выборку условием и параметром.
О_о Кто здесь?

ErrorEd88

Регистр ЛимитыКредиторскойЗадолженности нужно поместить во временную таблицу (или сделать вложенный запрос), после этого таблицу уже можно присоединять к документу поступление товаров и услуг левым соединением.
Я ошибся

no_limits

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

heroy

Примерно так:

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

            
            
1. Во вложенном запросе нет смысла группировать по огранизации,
   для группировки будет использоваться ключ по измерениям, поля в нужном порядке + задан четкий предикат по организации
2. Задать дополнительное ограничение по сумме для уменьшения левой таблицы Join,
   и уменьшения шанса эскалации блокировок при параллельной работе, так это перенесенный на более нижний уровень, стоимость операции
   будет меньше так как меньший объем данных   
3. Может показаться что для улучшения быстродействия, посредством уменьшения левой таблицы путем переноса условия
   (ПоступлениеТоваровИУслуг.Договор.ДоговорСПодрядчиком = ИСТИНА
            ИЛИ ПоступлениеТоваровИУслуг.Договор.ДоговорСПоставщиком = ИСТИНА) во вложенный запрос, но это не так,
   это поставит крест на использовании индекса на самой дорогой операции в запросе - группировке, что потянет за собой
   заметное падение быстродействия при увеличение объема данных
4. (ПоступлениеТоваровИУслуг.Сумма < &МинимальнаяСуммаЗадолженности
            ИЛИ ПоступлениеТоваровИУслуг.Сумма < ЛимитыКредиторскойЗадолженности.Сумма) - первую часть перенесли во вложенный запрос,
   итого осталось ПоступлениеТоваровИУслуг.Сумма < ЛимитыКредиторскойЗадолженности.Сумма а так как используется левое соединение и
   не используется ЕстьNULL то в случае отсутствия записи в левой таблицы все условие ГДЕ будет ложь, что эквивалентно поведению
   менее дорогой SQL операции Inner Join, поэтому заменим левое соединение на внутренне (то есть если для контрагента и договора не
   задан лимит в результат он не попадает)
5. знать бы реквизиты договора, можно было бы посмотреть дальше, булево имеет очень низкую селективность и с большой вероятностью
   вместо использования индекса может быть использована операция Table Scan
            

Vit1501

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

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

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

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

wok

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

iPach89

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

lobster13

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

//// Уберем из соединение подзапрос и поместим его во временную таблицу ЛИМИТЫ и с ней будем делать соединение.
Поле Организация и группировка по организации не нужны, так как выбираются записи по одной организации. В случае отсутствия записи по контрагенту будет Сумма NULL, учтем это.

cathrine

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

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

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

Поиск