8.х Вопрос по запросу

Тема в разделе "Конфигурирование на платформе "1С:Предприятие 8"", создана пользователем tunec, 26 фев 2009.

  1. TopicStarter Overlay
    tunec
    Offline

    tunec Опытный в 1С

    Регистрация:
    2 июн 2008
    Сообщения:
    469
    Симпатии:
    0
    Баллы:
    26
    Букафф много, но суть проста. И вопрос в принципе тоже не сложный и не подразумевает виртуозное владение языком запросов и даже умение читать чужой текст :unsure: .

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

    Если убрать подзапрос из объединения вообще - все работает верно.

    Стал ковыряться глубже наткнулся вот на что: Если в подзапросе "ВнутреннийЗапрос" убрать один из его подзапросов "ДвиженияДенежныхСредствОбороты" или "ЗаказПокупателя",то тоже все работает верно!
    результат выполнения "Внутреннего" запроса с отбором по одному документу:
    Суммаплатежей-------СтоимостьПродаж-------СуммаДокумента-------Заказ
    100---------------------<Пусто>-----------------------<Пусто>----------------Заказ1 //эту строку дает ДвиженияДенежныхСредствОбороты
    <Пусто>---------------<Пусто>-----------------------94700-------------------Заказ1 //эту строку дает ЗаказПокупателя

    Результат выполнения "Вложенного" запроса:
    Суммаплатежей--------СтоимостьПродаж--------Заказ
    100------------------------<Пусто>-------------------Заказ1


    Объясните почему так? В сети втречал только одно мнение - что порядок не важен, а тут получается по другому! Искал на ИТС и ЖК ниче не нашел...

    П.С. Код запроса писал не я, я исправляю багу, поэтому и стоит отбор по одному документу :) . Код писался конструктором запроса.

    П.П.С. 8.0.11.3 кажется так....
  2. BabySG
    Offline

    BabySG Администраторы Команда форума Администратор

    Регистрация:
    10 июн 2007
    Сообщения:
    11.853
    Симпатии:
    12
    Баллы:
    29
    1.
    Код:
    "ГДЕ
    ТоварыВРезервеНаСкладахОстатки.ДокументРезерва = &;ДокументРезерва"
    
    Вынести в параметры виртуальной таблицы. За такое увольняют.

    2.
    Код:
    "ПО ТоварыВРезервеНаСкладахОстатки.ДокументРезерва.Контрагент = ВзаиморасчетыСКонтрагентамиОстатки.ДоговорКонтрагента.Владелец"
    
    переписать нафиг! Через двойную точку обращения - это жесть!

    3. Общая рекомендация, что бы проще отлаживать было:

    Все используемые таблицы вынесите во временные, и потом уже формируйте все соединения. А то вообще чушь получается.
  3. KiberMath
    Offline

    KiberMath Опытный в 1С

    Регистрация:
    22 сен 2008
    Сообщения:
    61
    Симпатии:
    0
    Баллы:
    26
    почему через двойную точку это жесть?
  4. TopicStarter Overlay
    tunec
    Offline

    tunec Опытный в 1С

    Регистрация:
    2 июн 2008
    Сообщения:
    469
    Симпатии:
    0
    Баллы:
    26
    поясняю. Для отладки использование ГДЕ вместо параметров вирт таблиц весьма удобно, т.к. позволяет быстро копировать условия при отладке запроса сложной структуры (при разборе его составных частей) и а не скакать по коду выискивая куда же впихнуть его :) Этот код будет выполняться только на момент отладки, а поэтому не напряжет базу....

    речь пока идет не об оптимизации кода, а почему он не работает...

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

    потому что подразумевает получение объекта целиком и помещение его в память, что накладно при больших выборках. Этого можно было бы легко избежать используя привязку например по договору. Но опять же вопрос сейчас не в этом.
  5. KiberMath
    Offline

    KiberMath Опытный в 1С

    Регистрация:
    22 сен 2008
    Сообщения:
    61
    Симпатии:
    0
    Баллы:
    26
    Асилил запрос ))
    Действительно похожи на одинаковые они.

    Возможно это из-за ошибки в самой платформе, попробуй обновить до более поздней версии.
    Недавна например была проблема с запросами в 8.1.13.37.

    ЗЫ в 8.0 последняя версия была 8.0.13.32
  6. BabySG
    Offline

    BabySG Администраторы Команда форума Администратор

    Регистрация:
    10 июн 2007
    Сообщения:
    11.853
    Симпатии:
    12
    Баллы:
    29
    Нет - в запросе это вызывает неявное левое соединение с таблицей. Если это составной тип - будет создано столько же левых соединений. Представьте, что твориться, когда накладывается сверху РЛС!
  7. TopicStarter Overlay
    tunec
    Offline

    tunec Опытный в 1С

    Регистрация:
    2 июн 2008
    Сообщения:
    469
    Симпатии:
    0
    Баллы:
    26
    точно-точно, где-то читал об этом :) спасиб за напоминание.

Поделиться этой страницей