Продвинутый курс. Решение ДЗ №4
Представляем решение 4-го задания.
К сожалению, у Вас недостаточно прав для просмотра этой записи. Если Вы еще не залогинены на сайте
— залогиньтесь.
— залогиньтесь.
Если не активировали токен — посмотрите видео-инструкцию (видео N5)
Если вы залогинены, у Вас активирован токен доступа, но вы все равно видите эту запись —
напишите нам на e-mail поддержки.
выполнил
Евгений, опишите, пожалуйста, более подробно.
Смотрел Ваше решение, столкнулся с интересным поведением. Если я даю доступ на пустую номенклатурную группу, то это никак не учитывается, т.е. документы, содержащие номенклатуру с пустой ном. группой не отображаются. Это специально так задумано?
Нет, это не задуманное поведение.
Будем разбираться с неожиданным эффектом.
Мне кажется решение как в лекционном материале без вложенного запроса (за счет соединения таблиц) будет проще.
ПоступлениеТоваровИУслуг ИЗ Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПраваДоступаПользователей КАК ПраваДоступаПользователей
ПО (ПраваДоступаПользователей.Менеджеры = &Пользователь)
И ((НЕ ПоступлениеТоваровИУслуг.Товары.Номенклатура.НоменклатурнаяГруппа <> ПраваДоступаПользователей.НоменклатурныеГруппы))
Хотя техника построения запроса при изучении тоже, очень нужна.
Спасибо, Олег. Мы проанализируем, и модифицируем решение.
Почему эффект от применения следующих условий в соединении не равнозначный?
<code>
НЕ ПоступлениеТоваровИУслуг.Товары.Номенклатура.НоменклатурнаяГруппа <> ПраваДоступаПользователей.НоменклатурныеГруппы
ПоступлениеТоваровИУслуг.Товары.Номенклатура.НоменклатурнаяГруппа = ПраваДоступаПользователей.НоменклатурныеГруппы
</code>
На первый взгляд условия идентичны.
Можете привести пример, когда они дают разные результат?
В вашей базе после выполнения четвертого ДЗ. Добавил еще одну номенклатурную группу “Мягкая мебель”. Для номенклатуры “Диван” указал ее. Доступа пользователю Менеджер к этой номенклатурной группе не давал (он имеет
доступ только к Кухонной мебели). В консоли запросов следующий вариант возвращает ссылку на документ №2
ВЫБРАТЬ ПоступлениеТоваровИУслуг.Ссылка ИЗ РегистрСведений.ДоступПоГруппамНоменклатуры КАК ДоступПоГруппамНоменклатуры ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг ПО (ДоступПоГруппамНоменклатуры.НоменклатурнаяГруппа =
ПоступлениеТоваровИУслуг.Товары.Номенклатура.НоменклатурнаяГруппа) И (ДоступПоГруппамНоменклатуры.Пользователь = &Пользователь)
а в этом случае ссылок нет
ВЫБРАТЬ ПоступлениеТоваровИУслуг.Ссылка ИЗ РегистрСведений.ДоступПоГруппамНоменклатуры КАК ДоступПоГруппамНоменклатуры ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг ПО (НЕ ДоступПоГруппамНоменклатуры.НоменклатурнаяГруппа <>
ПоступлениеТоваровИУслуг.Товары.Номенклатура.НоменклатурнаяГруппа) И (ДоступПоГруппамНоменклатуры.Пользователь = &Пользователь)
&Пользователь равен Менеджеру.Причем явный вынос отрицания за скобки НЕ(А<>В) ничего не изменяет.
Хороший пример.
В первом запросе выдаются документы, где есть разрешенная номенклатурная группа (хотя бы одна).
Во втором запросе, выдаются документы, где все номенклатурные группы разрешены.
Объясняю действия системы во втором случае.
Поскольку накладывается условие на реквизит табличной части – происходит разыменование. В итоговый запрос будет добавлена табличная часть и соединение с ней.
То есть, условие НЕ АБ будет выполняться для каждой строки табличной части.
В частности для 4-ой строки документа №2 будет сформировано условие (НЕ КухоннаяМебель МягкаяМебель), очевидно условие возвращает Ложь.
Поскольку используется соединение по И, то и документ не войдет в результат запроса.
Подобный эффект получается только при разыменовании полей. В остальных случаях А = Б и Не А Б можно считать тождеством.
Тогда почему для первого запроса соединение происходит не по И? В противном случае, если бы соединение было по И, то для 4-ой строки документа условие (КухоннаяМебель=МягкаяМебель) тоже бы вернуло Ложь и эффект должен был бы быть тем же. Такое ощущение, что условие “НЕ” применяется уже на готовый набор ссылок и не используется при соединении табличной части документа и регистра сведений.
Верное замечение.
Точку в этом вопрос поставит анализ текстов запроса к СУБД.
На самом деле используется не логическое И, а оператор EXIST.
Вот данные запросов.
Для лучшего понимания привожу соответствие объектам метаданных.
_InfoRg176 – Регистр сведений
_Document11 – Документ Поступление товаров
_Document11_VT15 – табличная часть документа
_Reference9 – Справочник Номенклатура
1. ВЫБРАТЬ
ПоступлениеТоваровИУслуг.Ссылка
ИЗ
РегистрСведений.ДоступПоГруппамНоменклатуры КАК ДоступПоГруппамНоменклатуры
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг
ПО ДоступПоГруппамНоменклатуры.НоменклатурнаяГруппа = ПоступлениеТоваровИУслуг.Товары.Номенклатура.НоменклатурнаяГруппа
И (ДоступПоГруппамНоменклатуры.Пользователь = &Пользователь)
SELECT
T2._IDRRef
FROM _InfoRg176 T1
INNER JOIN _Document11 T2
ON (EXISTS(
SELECT 1
FROM _Document11_VT15 T3
LEFT OUTER JOIN _Reference9 T4
ON T3._Fld17RRef = T4._IDRRef
WHERE T2._IDRRef = T3._Document11_IDRRef AND ((T1._Fld178RRef = T4._Fld175RRef))) AND (T1._Fld177RRef = 0xBFCD00241DD40E2211DFF601F6D8A99F))
2. ВЫБРАТЬ
ПоступлениеТоваровИУслуг.Ссылка
ИЗ
РегистрСведений.ДоступПоГруппамНоменклатуры КАК ДоступПоГруппамНоменклатуры
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг
ПО ((НЕ ДоступПоГруппамНоменклатуры.НоменклатурнаяГруппа ПоступлениеТоваровИУслуг.Товары.Номенклатура.НоменклатурнаяГруппа))
И (ДоступПоГруппамНоменклатуры.Пользователь = &Пользователь)
SELECT
T2._IDRRef
FROM _InfoRg176 T1
INNER JOIN _Document11 T2
ON ((NOT (EXISTS(
SELECT 1
FROM _Document11_VT15 T3
LEFT OUTER JOIN _Reference9 T4
ON T3._Fld17RRef = T4._IDRRef
WHERE T2._IDRRef = T3._Document11_IDRRef AND (((T1._Fld178RRef T4._Fld175RRef)))))) AND (T1._Fld177RRef = 0xBFCD00241DD40E2211DFF601F6D8A99F))
Как можно заметить разница состоит только в условиях:
1. EXISTS(
SELECT 1
FROM _Document11_VT15 T3
LEFT OUTER JOIN _Reference9 T4
ON T3._Fld17RRef = T4._IDRRef
WHERE T2._IDRRef = T3._Document11_IDRRef AND ((T1._Fld178RRef = T4._Fld175RRef))) AND (T1._Fld177RRef = 0xBFCD00241DD40E2211DFF601F6D8A99F)
2. (NOT (EXISTS(
SELECT 1
FROM _Document11_VT15 T3
LEFT OUTER JOIN _Reference9 T4
ON T3._Fld17RRef = T4._IDRRef
WHERE T2._IDRRef = T3._Document11_IDRRef AND (((T1._Fld178RRef T4._Fld175RRef)))))) AND (T1._Fld177RRef = 0xBFCD00241DD40E2211DFF601F6D8A99F)
Таким образом, можно сказать, что
– 1 запрос выбирает документ, если есть хоть одна строка удовлетворяющая условию
– 2 запрос не выбирает документ, если есть хоть одна строка не удовлетворяющая условию равенства номенклатурных групп.
Анализирую в консоли
ВЫБРАТЬ
ПоступлениеТоваровИУслуг.Ссылка
ИЗ
Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПраваДоступаПользователей
КАК ПраваДоступаПользователей
ПО (не ПоступлениеТоваровИУслуг.Товары.Номенклатура.НоменклатурнаяГруппа <>
ПраваДоступаПользователей.НоменклатурныеГруппы
А= ПоступлениеТоваровИУслуг.Товары.Номенклатура.НоменклатурнаяГруппа
В= ПраваДоступаПользователей.НоменклатурныеГруппы
Док 1
Вилы – разрешен
Стол – разрешен
Табурет- запрещен
Док 2
Стол – разрешен
Док 3
Табурет – запрещен
А= В
Отбирает все документы, у которых разрешена хотя бы одна номенклатурная группа(Нам такие наборы не нужны).
Док 1
Док 2
А<>В
Отбирает все документы, у которых запрещена хотя бы одна номенклатурная группа
Док 2
Док 3
Не (А<>В)
Отбирает из двух отобранных (Док 2 и Док 3) инверсный, т.е. где есть разрешенные .
А=В не тоже самое что Не А<>В
Так как НЕ применяется к другому набору данных (уже отобранному).
Если я не прав исправите, пожалуйста.
Я не прав наверно так:
А<>В
Отбирает все документы, у которых запрещена хотя бы одна номенклатурная группа
Док 1
Док 3
Не (А<>В)
Отбираются инверсные, т.е. не попавшие в выборку из документов (Док 1 и Док 3) .
А=В не тоже самое что Не А<>В
Так как НЕ применяется к другому набору данных (уже отобранному).
Если я не прав исправите, пожалуйста.
Все правильно, Олег.
См. мой комментарий в этой же теме.
По моему, как-то усложнено.
Получается, в шаблоне получаем запрещенные номенклатурные группы. А потом в праве “Чтение” отрицаем полученное. А почему бы не использовать в шаблоне получение разрешенных и в “Чтение” использовать просто В(#…..) ? И запрос проще, и читается проще.
Спасибо, Александр!
Записал на доработку, несколько позже будем анализировать предложение.