CftClub.ru
Клуб специалистов ЦФТ-Банк

Интерпретация условия «OR» из PL/PLUS в PL/SQL

 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Настройка и сопровождение
Предыдущая тема :: Следующая тема  
Автор Сообщение
VSV056
Участник - экстремал


Вступление в Клуб: 25.11.2010
СообщениеВт Мар 24, 2015 07:57   Интерпретация условия «OR» из PL/PLUS в PL/SQL Ответить с цитатой
Полезность: Нет оценки
Коллеги, доброго дня!

Столкнулись с несколько непонятной работой интерпретатора PL/PLUS.

Задача: проверить условие того, что хотя бы один из счетов дебета или кредита платежного документа относятся к внебалансу, главе Г.

Логически приходящее решение (упрощенный синтаксис): [ACC_DT] = 'Г' OR [ACC_KT] = 'Г'

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

Смотрим во что преобразовалось наше условие в PL/SQL - оказывается [AC_FIN]
в итоговой выборке JOIN-ться к [MAIN_DOCUM] только один раз, в итоге в выборку один и тот же документ попадает дважды, если оба условия соединенные "OR" выполняются.

Скажите оно всегда так работало? Shocked
Или можно каким-то образом указать интерпретатору на необходимость нового JOINа [AC_FIN] для каждого условия "ИЛИ"?

Ниже пример кода, где первый вариант - с задвоением, второй рабочий.

Код:
begin
   debug_pipe('первый вариант',10);
   for v_doc in ::[MAIN_DOCUM] all
   where   (      v_doc.[ACC_DT].[MAIN_USV].[USV_US].[NEW_BS1].[RASD].[CHAPTER].[CHAPTER]='Г'
            or
               v_doc.[ACC_KT].[MAIN_USV].[USV_US].[NEW_BS1].[RASD].[CHAPTER].[CHAPTER]='Г'
         )
   and      v_doc=6830826889
   loop
      debug_pipe('v_doc = '||v_doc,10);
   end loop;
   debug_pipe('второй вариант',10);
   for v_doc in ::[MAIN_DOCUM] all
   where   'Г' in   (    v_doc.[ACC_DT].[MAIN_USV].[USV_US].[NEW_BS1].[RASD].[CHAPTER].[CHAPTER]
                  ,v_doc.[ACC_KT].[MAIN_USV].[USV_US].[NEW_BS1].[RASD].[CHAPTER].[CHAPTER]
               )
   and      v_doc=6830826889
   loop
      debug_pipe('v_doc = '||v_doc,10);
   end loop;
end;



Результат работы:

16:56:01 первый вариант
v_doc = 6830826889
v_doc = 6830826889
второй вариант
v_doc = 6830826889
Gobur
Профи


Вступление в Клуб: 06.11.2012
СообщениеВт Мар 24, 2015 10:16   Re: Интерпретация условия «OR» из PL/PLUS в PL/SQL Ответить с цитатой
Полезность: Нет оценки
Думаю тут дело в слишком глубокой вложенности на ПЛ+, что заставляет ядро автоматом связывать еще несколько таблиц. Тут либо самом эту связку прописывать ТБП, либо действительно IN использовать. Опять же эт она мой взгляд.
Damir
Участник - экстремал


Вступление в Клуб: 29.03.2013
СообщениеВт Мар 24, 2015 11:06   Re: Интерпретация условия «OR» из PL/PLUS в PL/SQL Ответить с цитатой
Полезность: Нет оценки
Gobur прав.
в запросах ПЛ+ обращение к каждому 'более вложенному' атрибуту приводит к добавлению таблицы в основной запрос ( в секцию from запроса SQL).
А вообще... жмите F12 и смотрите реальный SQL-запрос - без этого-то никак.
Damir
Участник - экстремал


Вступление в Клуб: 29.03.2013
СообщениеВт Мар 24, 2015 11:12   Re: Интерпретация условия «OR» из PL/PLUS в PL/SQL Ответить с цитатой
Полезность: Нет оценки
Код:
for v_doc in ::[MAIN_DOCUM] all
   where   
      exists(
         select m(m) in ::[MAIN_DOCUM] all
         where m = v_doc
            and m.[ACC_DT].[MAIN_USV].[USV_US].[NEW_BS1].[RASD].[CHAPTER].[CHAPTER]='Г'
      )
      or exists(
         select m(m) in ::[MAIN_DOCUM] all
         where m = v_doc
            and m.[ACC_KT].[MAIN_USV].[USV_US].[NEW_BS1].[RASD].[CHAPTER].[CHAPTER]='Г'
      )
   and      v_doc=6830826889

тока проверить надо - F12 и посмотреть чего получилось
budinva
Участник - экстремал


Вступление в Клуб: 15.01.2008
СообщениеСр Мар 25, 2015 16:03    Ответить с цитатой
Полезность: 1
не совсем конечно в тему, но проверять главу можно только по одной стороне, т.к. корреспонденция счетов с разными главами запрещена
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеЧт Мар 26, 2015 12:31   Re: Интерпретация условия «OR» из PL/PLUS в PL/SQL Ответить с цитатой
Полезность: Нет оценки
VSV056 пишет:

Пишем код, запускаем, получаем что все документы в выборке задваиваются. Удивляемся, т.к. логически вроде все верно.
Код:
begin
   debug_pipe('первый вариант',10);
   for v_doc in ::[MAIN_DOCUM] all
   where   (      v_doc.[ACC_DT].[MAIN_USV].[USV_US].[NEW_BS1].[RASD].[CHAPTER].[CHAPTER]='Г'
            or
               v_doc.[ACC_KT].[MAIN_USV].[USV_US].[NEW_BS1].[RASD].[CHAPTER].[CHAPTER]='Г'
         )
   and      v_doc=6830826889
   loop
      debug_pipe('v_doc = '||v_doc,10);
   end loop;
end;



Результат работы:

16:56:01 первый вариант
v_doc = 6830826889
v_doc = 6830826889


На мой взгляд, никакого противоречия нет.
Вы забываете, что переход по ссылке в pl+ - это присоединение таблицы в pl/sql.

То есть вы к документам присоединяете счета. Указываете, что счёт должен совпадать либо с ACC_DT, либо с ACC_KT.
Естественно, в таблице счетов оба счёта есть, то есть каждое из условий срабатывает.
Однако Oracle условие соединения строит несколько другое - выбрать из счетов такие счета, которые совпадают с полями документа дебетовым или кредитовым. Естественно, при такой постановке вопроса, к каждому счёту дублируется документ.
и чему ж вы таки удивляетесь?

Вы ж не написали
Код:
begin
   debug_pipe('первый вариант',10);
   for v_doc in ::[MAIN_DOCUM] all
   where   (      v_doc.[ACC_DT] in (select dt(dt) in ::[AC_FIN] where dt.[MAIN_USV].[USV_US].[NEW_BS1].[RASD].[CHAPTER].[CHAPTER]='Г' )
            or
               v_doc.[ACC_KT] in (select kt(kt) in ::[AC_FIN] where kt.[MAIN_USV].[USV_US].[NEW_BS1].[RASD].[CHAPTER].[CHAPTER]='Г')
         )
   and      v_doc=6830826889
   loop
      debug_pipe('v_doc = '||v_doc,10);
   end loop;
end;
VSV056
Участник - экстремал


Вступление в Клуб: 25.11.2010
СообщениеЧт Мар 26, 2015 12:47    Ответить с цитатой
Полезность: Нет оценки
Цитата:

На мой взгляд, никакого противоречия нет.
Вы забываете, что переход по ссылке в pl+ - это присоединение таблицы в pl/sql.

То есть вы к документам присоединяете счета. Указываете, что счёт должен совпадать либо с ACC_DT, либо с ACC_KT.
Естественно, в таблице счетов оба счёта есть, то есть каждое из условий срабатывает.
Однако Oracle условие соединения строит несколько другое - выбрать из счетов такие счета, которые совпадают с полями документа дебетовым или кредитовым. Естественно, при такой постановке вопроса, к каждому счёту дублируется документ.
и чему ж вы таки удивляетесь?


Все то, что вы расписали, было выяснено и понято еще на этапе анализа ошибки, еще до того как написать сюда (жмем F12 смотрим что получилось в итоговом коде).
Удивление вызвал тот факт, что за все время работы такая ситуация возникла впервые, раньше или подобных случаев не было или мы дважды OR из одной таблицы не делали... )))
Поэтому и удивление и вопрос - оно всегда так работало? Smile

Что еще могу от себя добавить - работа с PL/PLUS притупляет внимательность и отчасти расхолаживает. Смотришь вроде все верно - а по факту не так.
Так что как говорится на PL/PLUS надейся да сам не плошай)
Alkov
Профи


Вступление в Клуб: 23.09.2010
СообщениеПт Мар 27, 2015 05:23    Ответить с цитатой
Полезность: 1
В любой непонятной ситуации жми F12 Very Happy
Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Настройка и сопровождение Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Рейтинг@Mail.ru