Предикат по короткому условию

HOME_X
Дата: 16.02.2022 21:10:07
Доброго дня господа !

Имею запрос

select * 
   from T1
 where T1.F1=1
      or  T1.F2=2
      or  Exists(select 1 
                      from T2
                    where T2.F1=T1.F3 
                   ) 


Можно ли дать указание запросу работать по короткому условию констант (T1.F1=1) если это условие истинно,
не обращаться к таблице T2
И как это проверить

Спасибо !

Мысль такая
select * 
   from T1
 where T1.F1=1
      or  T1.F2=2
      or  Exists(select 1 
                      from T2
                    where T2.F1=T1.F3 
                       and T1.F1<>1
                       and T1.F2<>2
                   ) 
SY
Дата: 16.02.2022 21:38:48
HOME_X

Можно ли дать указание запросу работать по короткому условию констант (T1.F1=1) если это условие истинно,
не обращаться к таблице T2
И как это проверить


CASE:

SELECT  * 
  FROM  T1
  WHERE 1 = CASE
              WHEN T1.F1 = 1 THEN 1
              WHEN T1.F2 = 2 THEN 1
              ELSE (
                    SELECT  1
                      FROM T2
                      WHERE T2.F1 = T1.F3
                        AND ROWNUM = 1 
                    )
            END
/



как это проверить:

+
SQL> CREATE TABLE T1
  2    AS
  3      SELECT  1 F1,
  4              1 F2,
  5              1 F3
  6        FROM  DUAL
  7  /

Table created.

SQL> CREATE TABLE T2(F1 NUMBER)
  2  /

Table created.

SQL> SELECT  *
  2    FROM  T1
  3    WHERE 1 = CASE
  4                WHEN T1.F1 = 1 THEN 1
  5                WHEN T1.F2 = 2 THEN 1 / 0
  6                ELSE (
  7                      SELECT  1 / 0
  8                        FROM T2
  9                        WHERE T2.F1 = T1.F3
 10                          AND ROWNUM = 1
 11                      )
 12              END
 13  /

        F1         F2         F3
---------- ---------- ----------
         1          1          1

SQL> INSERT INTO T1 VALUES(2,2,2)
  2  /

1 row created.

SQL> SELECT  *
  2    FROM  T1
  3    WHERE 1 = CASE
  4                WHEN T1.F1 = 1 THEN 1
  5                WHEN T1.F2 = 2 THEN 1 / 0
  6                ELSE (
  7                      SELECT  1 / 0
  8                        FROM T2
  9                        WHERE T2.F1 = T1.F3
 10                          AND ROWNUM = 1
 11                      )
 12              END
 13  /
ERROR:
ORA-01476: divisor is equal to zero



no rows selected

SQL> SELECT  *
  2    FROM  T1
  3    WHERE 1 = CASE
  4                WHEN T1.F1 = 1 THEN 1
  5                WHEN T1.F2 = 2 THEN 1
  6                ELSE (
  7                      SELECT  1 / 0
  8                        FROM T2
  9                        WHERE T2.F1 = T1.F3
 10                          AND ROWNUM = 1
 11                      )
 12              END
 13  /

        F1         F2         F3
---------- ---------- ----------
         1          1          1
         2          2          2

SQL> INSERT INTO T1 VALUES(3,3,3);

1 row created.

SQL> INSERT INTO T2 VALUES(3);

1 row created.

SQL> SELECT  *
  2    FROM  T1
  3    WHERE 1 = CASE
  4                WHEN T1.F1 = 1 THEN 1
  5                WHEN T1.F2 = 2 THEN 1
  6                ELSE (
  7                      SELECT  1 / 0
  8                        FROM T2
  9                        WHERE T2.F1 = T1.F3
 10                          AND ROWNUM = 1
 11                      )
 12              END
 13  /
ERROR:
ORA-01476: divisor is equal to zero



no rows selected

SQL> SELECT  *
  2    FROM  T1
  3    WHERE 1 = CASE
  4                WHEN T1.F1 = 1 THEN 1
  5                WHEN T1.F2 = 2 THEN 1
  6                ELSE (
  7                      SELECT  1
  8                        FROM T2
  9                        WHERE T2.F1 = T1.F3
 10                          AND ROWNUM = 1
 11                      )
 12              END
 13  /

        F1         F2         F3
---------- ---------- ----------
         1          1          1
         2          2          2
         3          3          3

SQL>


SY.
HOME_X
Дата: 16.02.2022 22:14:27
SY,

Понял Вас !

Надеялся увидеть параметры настройки базы на манер Hint-ов
У Delphi есть аналогичное - анализ короткой или полной логики условия

Но так тоже подойдет !
Спасибо
ASNexus
Дата: 16.02.2022 22:41:11
HOME_X
Доброго дня господа !

Имею запрос

select * 
   from T1
 where T1.F1=1
      or  T1.F2=2
      or  Exists(select 1 
                      from T2
                    where T2.F1=T1.F3 
                   ) 

Можно ли дать указание запросу работать по короткому условию констант (T1.F1=1) если это условие истинно,
не обращаться к таблице T2
И как это проверить

Этот запрос будет выполняться именно так, как Вам нужно: в первую очередь производится проверка условий, в которых сравнение с константами, в т.ч. IS [NOT] NULL, потом уже выполнение подзапросов, вызовы функций и т.п. Независимо от порядка этих условий в WHERE.
Где это прочитать в доке - так с ходу не вспомню. Проверить можно примерами на разных исходных данных, вроде тех, что SY ниже написал.
ASNexus
Дата: 16.02.2022 22:52:06
Кстати, MSSQL в подзапросах [NOT] EXISTS игнорирует всё, что перечислено в его SELECT (может быть это регулируется параметрами - тут не скажу, не знаю), т.е. можно написать что-то вроде "where exists (select 1/0 from ...)" и это не вызовет ошибку "divisor is equal to zero". Возможно Oracle в какой-то версии это тоже сделает (или уже сделал). Исходя из этого, я бы для проверки того, выполняется подзапрос или нет добавил бы условие в WHERE подзапроса, что-то вроде "and T2.F1 / 0 > 0"
SQL*Plus
Дата: 16.02.2022 23:47:22
ASNexus
Кстати, MSSQL в подзапросах [NOT] EXISTS игнорирует всё, что перечислено в его SELECT
(может быть это регулируется параметрами - тут не скажу, не знаю),
т.е. можно написать что-то вроде "where exists (select 1/0 from ...)" и это не вызовет ошибку "divisor is equal to zero".

Возможно Oracle в какой-то версии это тоже сделает (или уже сделал).
Исходя из этого, я бы для проверки того, выполняется подзапрос или нет
добавил бы условие в WHERE подзапроса, что-то вроде "and T2.F1 / 0 > 0"


SQL> SELECT banner_full FROM v$version;

BANNER_FULL                                                                                                                                                     
-------------------------------------------------------------------------------
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.4.0.0.0

SQL> SELECT D.department_id, D.department_name 
  2  FROM departments D
  3  WHERE NOT EXISTS (SELECT 1/0 FROM employees E 
  4                    WHERE D.department_id = E.department_id)
  5    AND ROWNUM <= 3;

DEPARTMENT_ID DEPARTMENT_NAME               
------------- ------------------------------
          120 Treasury                      
          130 Corporate Tax                 
          140 Control And Credit  

Предполагаю, что в предыдущих версиях Oracle Database было такое же поведение,
поскольку не имеет значения, что будет в списке выборки кореллированного подзапроса.

Лично я обычно там ставлю * (звездочку).
Sayan Malakshinov
Дата: 17.02.2022 01:30:13
ASNexus
Кстати, MSSQL в подзапросах [NOT] EXISTS игнорирует всё, что перечислено в его SELECT
Oracle тоже.
ASNexus
"where exists (select 1/0 from ...)" и это не вызовет ошибку "divisor is equal to zero"
смотрите внимательнее, там где ошибка, там было не exists, а просто скалярный подзапрос.
ASNexus
я бы для проверки того, выполняется подзапрос или нет добавил бы условие в WHERE подзапроса, что-то вроде "and T2.F1 / 0 > 0"
вообще это не очень хороший способ проверять, что выполняется...
HOME_X
Дата: 17.02.2022 21:31:20
Sayan Malakshinov,

В качестве проверки использовал поль. функцию , в которую передаю
уникальное значение записи и это значение выводиться в консоль

В целом процесс отслеживается

select * 
   from T1
 where T1.F1=1
      or  T1.F2=2
      or  Exists(select 1 
                      from T2
                    where T2.F1=T1.F3 
                        and MyFunc(T1.F3)=1
                   ) 


ASNexus
Насчет последовательности - Вы правы - первично идут константы.
Ссылка на таблицу в последную очередь

Спасибо
andreymx
Дата: 21.02.2022 00:08:23
HOME_X,

когда вы добавили and MyFunc(T1.F3)=1
то получили совершенно другой запрос
andreymx
Дата: 21.02.2022 00:08:51
HOME_X
Насчет последовательности - Вы правы - первично идут константы.
Ссылка на таблицу в последную очередь
а какие индексы у вас есть?