Почему не работает левое соединение

Почему не работает левое соединение

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

Например, мы хотим выбрать все документы «Заказ клиента» за какой-то период и соединить каждый из них со своим значением дополнительного сведения «Вип заказ», которое имеет тип «Булево» и хранится в регистре сведений «Дополнительные сведения».

Нужно помнить, что в указанном регистре сведений находятся не все документы «Заказ клиента», а только те, у которых значение дополнительного сведения «Вип заказ» установлено в «Да».

Итак, пишем запрос:

В выборке этого запроса мы увидим результат не «Левого соединения», которое мы указали в тексте запроса, а «Внутреннего соединения». В выборке окажутся только те документы «Заказ клиента», которые присутствуют в правой таблице – «ДополнительныеСведения».

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

Решение с использованием временной таблицы:

Решение с использованием вложенного запроса:

Оба эти варианты запросов дадут в итоге настоящее «Левое соединение»: в выборку попадут все документы «Заказ клиента» из левой таблицы и значения дополнительного сведения из правой таблицы для тех документов, у которых это сведение задано.

Комментарии

Можно сделать так:

Запрос.Текст = «ВЫБРАТЬ
| ЗаказыКлиентов.Ссылка КАК ЗаказКлиента,
| ДополнительныеСведения.Значение КАК ЭтоВипЗаказ
|ИЗ
| Документ.ЗаказКлиента КАК ЗаказыКлиентов
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения
| ПО (ЗаказыКлиентов.Ссылка = ДополнительныеСведения.Объект)
| И ДополнительныеСведения.Свойство = &СвойствоДопСведения»;

Источник

v8: Не работает левое соединение! Все-таки работает

Доброй ночи! А вернее доброго утро! Уже 5-тый час, а не могу справится с запросом. Выручайте!
Привожу в пример упрощенный вариант и описание всего что я с ним делал и где он не работал.
Вот запрос:
Запрос.Текст = «ВЫБРАТЬ
| КонтактныеДанные.Адрес КАК Адрес,
| КонтактныеДанные.Телефон,
| ВЫРАЗИТЬ(КонтактныеДанные.Контрагент КАК Справочник.Контрагенты) КАК Контрагент,
| ЗаказНаряд.Ссылка,
| ЗаказНаряд.Заказчик
|ИЗ
| Документ.ЗаказНаряд КАК ЗаказНаряд
| ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
| КонтактнаяИнформацияАдрес.Представление КАК Адрес,
| ВЫРАЗИТЬ(КонтактнаяИнформацияАдрес.Объект КАК Справочник.Контрагенты) КАК Контрагент,
| КонтактнаяИнформацияТелефон.Представление КАК Телефон
| ИЗ
| РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформацияАдрес
| ПОЛНОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформацияТелефон
| ПО КонтактнаяИнформацияАдрес.Объект = КонтактнаяИнформацияТелефон.Объект
| ГДЕ
| КонтактнаяИнформацияАдрес.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Адрес)
| И КонтактнаяИнформацияАдрес.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.АдресПочтовый)
| И КонтактнаяИнформацияТелефон.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон)
| И КонтактнаяИнформацияТелефон.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонКонтактный)
| И КонтактнаяИнформацияАдрес.Объект ССЫЛКА Справочник.Контрагенты
| И КонтактнаяИнформацияТелефон.Объект ССЫЛКА Справочник.Контрагенты) КАК КонтактныеДанные
| ПО ЗаказНаряд.Заказчик.Код = КонтактныеДанные.Контрагент.Код»;

Источник

Не работает ЛЕВОЕ или ПОЛНОЕ соединение

Платформа 8.2 УПП 1.3 с огромным количеством дописок и доделок.
В системе создается каждый день документ, называется «Просрочка», в котором еженощно пересчитываются количество дней просрочки контрагентов, сумма задолженности, сумма просроченной задолженности и т.д. Пытаюсь объединить взаиморасчеты и этот документ Следующим запросом:

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

И все бы хорошо, но тех контрагентов, которые закрыли задолженность в указанный период в документе «Просрочка» уже нет, там только должники. Насколько я понимаю, при полном и левом соединении, этот запрос должен возвращать NULL в поля которых не существует в документе просрочки, однако запрос тупо выкидывает из результата этих контрагентов, хотя во взаиморасчетах они есть.
Помогите пожалуйста понять, что я делаю не так.

Источник

Левое соединение работает как внутреннее

Мне нужно запросом получить реквизит документа и значение из его табличной части, при этом табличная часть у документа может отсутствовать (зависит от вида операции)

Читайте также:  Не работает полный привод ниссан мурано z50

1) В таком варианте левое соединение работает как внутреннее, то есть, если в документе ТЧ отстутсвует, то такие документы не попадают в результат (потому что система не может сравнить с NULL??)

2) А вот так почему то работает

Подскажите, пожалуйста, почему 2) работает (в результате присутствуют документы, у которых нет ТЧ) в отличии от 1).

Как ПРАВИЛЬНО решать такую задачу (проверять на NULL?)

Первая получает только значение Ссылки. Вторая считывает целиком Документ и уже от него получает значение Ссылки.

По поводу (1). Или итоговый запрос имеет не совсем такую структуру.
Или это не чисто запрос, а используется в СКД. Там да, это возможно. Но решается по другому.

ВЫБРАТЬ
УчетРаботы.Ссылка,
УчетРаботы.Организация
ПОМЕСТИТЬ вт
ИЗ
Документ.УчетРаботы КАК УчетРаботы
ГДЕ
УчетРаботы.Дата МЕЖДУ &Дата1 И &Дата2
И УчетРаботы.Проведен
;

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

Что не так с его структурой? Запрос прекрасно работает, за исключением того что возвращает только те документы у которых ТЧ Факт заполнена. то есть вместо левого соединения по факту получается внутреннее

Источник

СКД — одна из проблем связи Наборов данных

Доброго времени суток.

Вступление

Собственно все началось с простого задания — есть номенклатура (список номенклатуры), собираемая по спецификации. Надо вывести сколько комплектующих надо для сборки, сколько есть на складах, чтобы принять решение о закупках, сборке, передачах. (Складов много)

Суть проблемы простая — пока в отчете нет отборов (список номенклатуры задается параметром) то схема из нескольких Наборов данных работает хорошо и правильно. Но стоит задать отбор по складу — можно получить пустой отчет. Итак по-порядку. (Конфигурация УПП, так что тексты запросов соответствующие)

1. Подготовка и демонстрация

НаборДанных1 (основная выборка) с полями Комплектующая, Продукция и КоличествоНа1 (среднее взял, потому что бардак в спецификации) — запрос:

ВЫБРАТЬ
СпецификацииНоменклатурыВыходныеИзделия.Номенклатура КАК Продукция,
СпецификацииНоменклатурыИсходныеКомплектующие.Номенклатура КАК Комплектующая,
СРЕДНЕЕ(СпецификацииНоменклатурыИсходныеКомплектующие.Количество / ВЫБОР
КОГДА СпецификацииНоменклатурыВыходныеИзделия.Количество <> 0
ТОГДА СпецификацииНоменклатурыВыходныеИзделия.Количество
ИНАЧЕ 1
КОНЕЦ) КАК КоличествоНа1
ИЗ
Справочник.СпецификацииНоменклатуры.ВыходныеИзделия КАК СпецификацииНоменклатурыВыходныеИзделия
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.СпецификацииНоменклатуры.ИсходныеКомплектующие КАК СпецификацииНоменклатурыИсходныеКомплектующие
ПО СпецификацииНоменклатурыВыходныеИзделия.Ссылка = СпецификацииНоменклатурыИсходныеКомплектующие.Ссылка
ГДЕ
СпецификацииНоменклатурыВыходныеИзделия.Ссылка.Активная
И СпецификацииНоменклатурыВыходныеИзделия.Номенклатура В ИЕРАРХИИ(&Номенклатура)

СГРУППИРОВАТЬ ПО
СпецификацииНоменклатурыВыходныеИзделия.Номенклатура,
СпецификацииНоменклатурыИсходныеКомплектующие.Номенклатура

НаборДанных2 (остатки, зависимый) — запрос:

ВЫБРАТЬ
ТоварыНаСкладахОстатки.Склад КАК СкладКомплектующей,
ТоварыНаСкладахОстатки.Номенклатура КАК Комплектующая,
ТоварыНаСкладахОстатки.КоличествоОстаток КАК ОстатокКомплектующей
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(<(&КонецПериода)>, <(Склад).* КАК СкладОтбора, (Номенклатура).* КАК Комплектующая>) КАК ТоварыНаСкладахОстатки

Здесь немного поясню: я разделил Склад на поле «выборки» и поле «отбора», т.е. в отборах будет поле СкладОтбора, но его нельзя выбирать в Выбранные поля, хотя СкладКомплектующей тоже можно отбирать. Причина — в хотелке, но об этом ниже.

Связи наборов данных: Источник — НаборДанных1 (основной), Приемник — НаборДанных2 (зависимый), Выражения — Комплектующая.

Ресурсы пока простые: Сумма(КоличествоНа1) и Сумма(ОстатокКомлектующей).

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

Выполняю. Получаю ожидаемый результат — все есть, все хорошо:

Дальше была идея Склады в колонки, но тогда получается очень широко и почти не заполнено. Ну если одна комплектующая только на одном складе, то по всем остальным пусто. В общем не очень красиво выходит.

Проблема:

Но вот я задаю отбор «Склад отбора Равно Цех готовой продукции» и результат — только одна комплектующая:

Тогда я еще не знал про «замену Левого на Внутреннее, если есть отбор».

2. Попытка выкрутиться

В статье «СКД — наборы данных и связи между ними. » есть пункт «Некоторые особенности соединения наборов данных» с подпунктом «Отбор по полю подчиненного набора«, где сказано «если необходимо получить все данные из основного набора, нужно наложить отбор на уровне группировки отчета».

Читайте также:  Как настроить оперу для гугла

Но вот беда: в отборе по группировке, среди доступных полей, нет поля «СкладОтбора»:

Хорошо, попробую использовать СкладКомплектующей. Добавил отборы в каждую группировку, но выключенные и стал включать по очереди. Первым включаю у группировки Комплектующая. Результат такой же, как с отбором по отчету целиком. Отключаю.

Включаю следующий — отбор у группировки Продукции. Уже лучше — все Комплектующие появились, а вот продукции нет. Да и остатки комплектующих странные — по группировке остатки показаны, а из чего получились, откуда взялись?

Отключаю у Продукции. Включаю последний отбор — у детальных записей. Почти идеальный результат, по крайней мере продукция появилась. Но с Остатками по-прежнему: по складам 46, а у группировок — 107 с хвостом. По остальным и того хуже.

Итог: либо я не так понял, либо не то делаю. Но и это не работает. Да и пользователям пояснять в какой ветке нужно поставить отбор — тяжело (прибабахи толстого клиента, где проще дать возможность редактировать настройку, чем вытащить что-то из глубины структуры на форму)

3. Хотелки и их исполнение.

Кому интересно решение проблемы — этот пункт можно пропустить.

Хотелка 1 — а почему не добавить показ остатков по Продукции?

Хотелка 2 — как бы сделать отчет более смотребильным, а то складов много и увидеть остатки сразу в строке — значит надо склады в колонки, а тогда отчет получается «разряженным».

Хотелка 3 — если уж добавил остатки продукции, то отбор по складу должен работать и на это.

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

ВЫБРАТЬ
ТоварыНаСкладахОстатки.Склад КАК СкладПродукции,
ТоварыНаСкладахОстатки.Номенклатура КАК Продукция,
ТоварыНаСкладахОстатки.КоличествоОстаток КАК ОстатокПродукции
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(<(&КонецПериода)>, <(Склад).* КАК СкладОтбора, (Номенклатура).* КАК Продукция>) КАК ТоварыНаСкладахОстатки

Тут интересный эффект наблюдал, если поле Склад будет иметь одинаковое наименование в обоих подчиненных наборах, то в результате в остатках у продукции будет не правильный склад, потому что значение будет от первого набора. Поэтому — они разные. Одинаковыми могут быть только действительно одинаковые по смыслу поля, например те которые участвуют в связи. Так Номенклатура для НабораДанных2 называется Комплектующая, а в НабореДанных3 — Продукция. Ну а чтобы поле отбора было единым для обоих наборов: появился СкладОтбора — это решило хотелку 3.

Ну и добавляем еще одну связь.

Ну и в ресурсах определяем ОстатокПродукции.

Теперь вторая хотелка. Если выводить данные по складам списком — получим умножение строк остатков, например 5 складов по Комплектующей и 3 по Продукции итого 15 строк. Хорошо хоть итоги по группировкам правильные. Да и как «сложить» 2 одинаковых склада по комплектующей и по продукции? Поля называются по разному и как сделать по ним группировку — не придумал.

Тут на помощь пришла вторая статья Агрегатные функции СКД, о которых мало кто знает. Сначала использовал функцию ТаблицаЗначений. Но при простом повторении формирования отчета строки складов прыгают. Тогда добавил Упорядочить в итоге получилось так:

Для ОстаткаКомплектующих: Упорядочить(ТаблицаЗначений(Различные СкладКомплектующей Как Склад, ОстатокКомплектующей Как Остаток), «Склад Автоупорядочивание»)

Для ОстаткаПродукции: Упорядочить(ТаблицаЗначений(Различные СкладПродукции Как Склад, ОстатокПродукции Как Остаток), «Склад Автоупорядочивание»)

Дальше немного «причесал» структуру: выключил детальные записи, сгруппировал поля, отключил «Общие Итоги по вертикали».

В результате получил — строки группировки «пухнут» в зависимости от количества складов, но видно где, чего и сколько, просто посмотрев по строке. Поставил в ресурсах «Расчитывать по. » (как на картинке выше) и по крайне мере для Комплектующей убрались остатки по складам из колонки остатков продукции. Вот такой результат получил:

Читайте также:  Киа рио не работает гудок

Теперь влючаю отбор по складу и вижу результат, опять исчезли строки (что в прочем уже ожидаемо):

4. Поиск решения

Сразу скажу: на мой взгляд не очень хорошее, но другого не нашел. Вопросы такого плана есть, а ответов увы не много. Потому думал сам и пришел к выводу — если связь вместо ЛЕВОЙ становится ВНУТРЕННЕЙ, значит необходимо сделать так, чтобы для каждой записи основного набора существовала запись зависимого, не взирая на отбор.

И тут у меня возникла сложность — я не очень хорошо понимаю в какой момент накладывается отбор при формировании. Потому решил пойти простым путем — эксперимента. Первое что попробовал — изменить запрос остатков: к справочнику номенклатуры Левым соединением добавил Остатки. На тот момент это выглядело так (не использовать, почему — ниже):

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

Дальше экспериментировал с настройками. Работало долго. На каком-то этапе вообще получил от сервера отлуп по памяти. Бросил.

Пробовал создать набор типа Объединение, где один набор — остатки, другой — опять же номенклатура. Но там надо было создавать сложные условия с ИЛИ, чтобы запись Номенклатуры выбиралась в любом случае. Не пошло.

День бодался. На следующий день пошел по второму кугу. Только все создавал с нуля.

5. Решение

И начал снова с Левого соединения в запросе. Получился такой запрос (правильный):

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

Сформировал, посмотрел нормальный результат. Включил отбор и увидел это:

Стал сравнивать с предыдущими тестами и понял: <ГДЕ ТоварыНаСкладахОстатки.Склад.* КАК СкладОтбора>отрабатывала после соединения, а потому отсекало номенклатуру. А когда я перенес его в условия таблицы остатков, то и отбор сработал только на регистр остатков не затронув номенклатуру. Потому первый запрос — не правильный и не работает, а второй заработал (так я считаю).

Но самым удивительным для меня оказался такой результат (отбор по другому складу и еще одна продукция):

Чем удивило? А тем, что Левое соединение я делал только в одном наборе данных — во втором (по комплектующим), а в третьем — как было, так и осталось. Почему же группировка по Продукции не пропала? Почему остатки выдает правильные с учетом отбора? Вывод получился такой — а третий набор, несмотря на то что к нему был применен отбор, все-равно имеет ЛЕВОЕ соединение. Возможно свою лепту вносит тот факт, что для второго и третьего набора один и тот же отбор. Возможно третий слепили со вторым, а потом только с первым.

Правильный вывод или нет — я не знаю.

В общем дальше можно пытаться улучшить. Например, если основной запрос не сложный, то в НабореДанных2 связывать не со справочником номенклатуры, а поместить результат основного запроса во временную таблицу и связать с ним.

Конец

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

Источник

Оцените статью