powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Где лучше указывать условие, в join или where?
10 сообщений из 35, страница 2 из 2
Где лучше указывать условие, в join или where?
    #39319487
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexFF__|Так что извини, но мне кажется, что ты путаешь не только ТС
Я, как бы, живой и могу сам ответить.
Я понял, что в целом всегда следует придерживаться семантики.
А чтобы делать что-то нестандартно, то нужно хорошо знать, как устроено «под капотом».
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319500
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous...
То, что значение выражения не определено для t1.id = 2 в рамках трехзначной логики означает, что выражение не истинно и строка во множество, определенное предикатом, не входит.
Таким образом, тезис, о том, что SQL-запрос "ДОЛЖЕН давать ошибку" в указанной ситуации - на самом деле ложен...

В целом - браво, и красиво соответствует определению операции сравнения в sql
Но -

andrey_anonymous...
(ну нет в ЯЗЫКЕ SQL средств для работы с исключительными ситуациями)...
...

это не совсем (совсем не) так.
sql-99 явно определяет семантику исключительных ситуаций для вычислений.
В частности, ISO/IEC 9075-2:1999 (E)
6.17 <numeric value function>
<cardinality expression> ::=
CARDINALITY <left paren> <collection value expression> <right paren>
<absolute value expression> ::=
ABS <left paren> <numeric value expression> <right paren>
<modulus expression> ::=
MOD <left paren> <numeric value expression dividend> <comma>
<numeric value expression divisor><right paren>
<numeric value expression dividend> ::= <numeric value expression>
<numeric value expression divisor> ::= <numeric value expression>
...
далее -
...
10) If <modulus expression> is specified, then let N be the value of the immediately contained
<numeric value expression dividend> and let M be the value of the immediately contained
<numeric value expression divisor>.
Case:
a) If either N or M is the null value, then the result is the null value.
b) If M is zero, then an exception condition is raised: data exception — division by zero.
c) Otherwise, the result is the unique nonnegative exact numeric value R with scale 0 (zero)
such that all of the following are true:
i) R has the same sign as N.
ii) The absolute value of R is less than the absolute value of M.
iii) N = M * K + R for some exact numeric value K with scale 0 (zero).

andrey_anonymous...
Беспокоить может лишь нестабильность результата (то набор данных, то аварийное завершение в зависимости от положения звезд на небе) - и подобное поведение (if any) мы смело запишем в недостатки конкретной реализации.
...
ну да.
Вот это - результат (состояние курсора при возникновении run-time error) как раз и оставлено на взгляд implementation.
Что как-бы обессмысливает теоретическую красоту интертрепации результата логического выражения.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319513
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousDimitry Sibiryakovпропущено...

В данном случае она "предшествует" чисто синтаксически. То есть выделенное предложение
говорит, что WHERE в тексте запроса стоит после FROM и ничего больше.

Коллеги, это уже детский сад.
Соломон показал, что оно:
- так работает
- так реализовано
- так описано в стандарте

То, что в частных конкретных случаях (включая innser join) фильтры могут без нарушения логики быть протолкнуты непосредственно к rowsource - не меняет принципа.
Логически предикаты where применяются к множеству, определенному from.
Точка.
Если начинающий программист будет воспринимать это именно так - не допустит дурацких ошибок, которыми бывает пересыпан код начинающих, не осознающих разницы.Все дело лишь в точности формулировок.

1. Если утверждать что where применяется после, то некоторые могут захотеть писать
Код: plsql
1.
2.
3.
select *
from t1
join (select * from t2 where t2.status > 0) t2 on (t2.type_id = t1.type_id)

Можно сказать, что это надо быть совсем чайником. Ну так если б ТС умел читать планы - у него и вопроса бы не возникло.

2. Формулировки, что предикаты "могут быть протолкнуты" или "оптимизатор может решить" верны в теории.
На практике, предикаты по внешней таблице никогда не будут применены до, предикаты исключительно по внутренней всегда будут применены до.
Полагаю тут как не играйся на двух таблицах хоть с предикатами по UDF + associate statistics + отключение всех трансформаций + что угодно - внутренний rowsource будет отфильтрован до соединения когда это возможно.

3. Ну и рассказывать про порядок применения на основании expand_sql_text и обычных (не коррелированных, не non-mergeable) inline view - это уж совсем некорректно. Тем более final query в 10053 выглядит несколько иначе.

Так что просто надо разделять теорию и практику.

SY, спасибо за цитату. Пропустил файл "5WD-02-Foundation-2003-09.pdf" для стандарта SQL:2003.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319539
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshop...Все дело лишь в точности формулировок.

1. Если утверждать что where применяется после, то некоторые могут захотеть писать
Код: plsql
1.
2.
3.
select *
from t1
join (select * from t2 where t2.status > 0) t2 on (t2.type_id = t1.type_id)

Можно сказать, что это надо быть совсем чайником....

дело, имхо, в другом.
Давайте все же внешнее соединение...
Вот тут -
Код: plsql
1.
2.
select *
from t1,  t2 where t2.status > 0 And t2.type_id(+) = t1.type_id


надо полагать - чайником, т.к. из outer превратится в inner
а тут?
Код: plsql
1.
2.
select *
from t1 left join  t2 on t2.status > 0 Or t2.type_id = t1.type_id


это вообще нельзя выписать без union в традиционном синтаксисе, при совершенно ясной семантике.
т.е. - от перемены мест чайник кипит при разных температурах.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319602
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
boobydbms_photoshop...Все дело лишь в точности формулировок.

1. Если утверждать что where применяется после, то некоторые могут захотеть писать
Код: plsql
1.
2.
3.
select *
from t1
join (select * from t2 where t2.status > 0) t2 on (t2.type_id = t1.type_id)

Можно сказать, что это надо быть совсем чайником....

дело, имхо, в другом.
Давайте все же внешнее соединение...
Вот тут -
Код: plsql
1.
2.
select *
from t1,  t2 where t2.status > 0 And t2.type_id(+) = t1.type_id


надо полагать - чайником, т.к. из outer превратится в inner
а тут?
Код: plsql
1.
2.
select *
from t1 left join  t2 on t2.status > 0 Or t2.type_id = t1.type_id


это вообще нельзя выписать без union в традиционном синтаксисе, при совершенно ясной семантике.
т.е. - от перемены мест чайник кипит при разных температурах.Если обсуждать мышление чайников и абстрактные запросы в вакууме можно вообще далеко зайти.
Так что, желательно хоть немного понимать что требуется получить.

В первом случае, очевидно, отсутствие плюса в "t2.status > 0" делает этот предикат post join.
Если вспользоваться case намекая на "неразрывность условий", то получим соответствующие ошибки
11g
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
SQL> with t1 as (select 1 type_id, 1 status from dual),
  2  t2 as (select 1 type_id, 1 status from dual)
  3  select *
  4    from t1, t2
  5   where case when t2.status > 0 and t2.type_id(+) = t1.type_id then 1 end = 1;
 where case when t2.status > 0 and t2.type_id(+) = t1.type_id then 1 end = 1
                                                                         *
ERROR at line 5:
ORA-01417: a table may be outer joined to at most one other table


12c
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
SQL> with t1 as (select 1 type_id, 1 status from dual),
  2  t2 as (select 1 type_id, 1 status from dual)
  3  select *
  4    from t1, t2
  5   where case when t2.status > 0 and t2.type_id(+) = t1.type_id then 1 end = 1;
 where case when t2.status > 0 and t2.type_id(+) = t1.type_id then 1 end = 1
                                                                         *
ERROR at line 5:
ORA-01416: two tables cannot be outer-joined to each other



Во втором случае, если таки цель все сделать предикатами соединения (то есть догадавшись поставить (+)), получим
11g, 12c
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
SQL> with t1 as (select 1 type_id, 1 status from dual),
  2  t2 as (select 1 type_id, 1 status from dual)
  3  select *
  4    from t1, t2
  5   where t2.status(+) > 0 or t2.type_id(+) = t1.type_id;
 where t2.status(+) > 0 or t2.type_id(+) = t1.type_id
                                         *
ERROR at line 5:
ORA-01719: outer join operator (+) not allowed in operand of OR or IN


или применив вышеупомянутый прием с case
11g, 12c
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
SQL> with t1 as (select 1 type_id, 1 status from dual),
  2  t2 as (select 1 type_id, 1 status from dual)
  3  select *
  4    from t1, t2
  5   where case when t2.status(+) > 0 or t2.type_id(+) = t1.type_id then 1 end = 1;

   TYPE_ID     STATUS    TYPE_ID     STATUS
---------- ---------- ---------- ----------
         1          1          1          1
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319619
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshopили применив вышеупомянутый прием с case


Ну вот и expand пригодился.

dbms_photoshopНу и рассказывать про порядок применения на основании expand_sql_text и обычных (не коррелированных, не non-mergeable) inline view - это уж совсем некорректно. Тем более final query в 10053 выглядит несколько иначе.


Конечно иначе. Но экспанд, помимо прочего, показывает как выглядит SQL пользователя который в общем случае написан на ANSI SQL перeведенный на нативный Oracle SQL. И показывал я его только с этой точки зрения, т.е. с точки зрения логики а не имплементации - как ANSI SQL с отдельными ON и WHERE транслируется в Oracle SQL где есть тoлько WHERE при этом coблюдая логику результата. Ну а дальше, как я и говорил, колдует оптитизатор.

SY.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319674
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshop1. Если утверждать что where применяется после, то некоторые могут захотеть писать

Не "после", а "к" - однако разница

dbms_photoshop2. Формулировки, что предикаты "могут быть протолкнуты" или "оптимизатор может решить" верны в теории.
На практике, предикаты по внешней таблице никогда не будут применены до, предикаты исключительно по внутренней всегда будут применены до.
Никогда не говори "никогда":
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
explain plan for 
select * from t1
left join t2 on (t1.id=t2.id)
where t1.id = 5 and t2.id = 5;
Explained

select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1819147781
--------------------------------------------------------------------------------
| Id  | Operation                  | Name | Rows  | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |      |     1 |    26 |    17   (0)| 00:00:0
|*  1 |  HASH JOIN                 |      |     1 |    26 |    17   (0)| 00:00:0
|*  2 |   TABLE ACCESS STORAGE FULL| T1   |     1 |    13 |    10   (0)| 00:00:0
|*  2 |   TABLE ACCESS STORAGE FULL| T2   |     1 |    13 |     7   (0)| 00:00:0
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("T1"."ID"="T1"."ID")
   2 - storage("T1"."ID"=5)
       filter("T1"."ID"=5)
   3 - storage("T2"."ID"=5)
       filter("T2"."ID"=5)
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319694
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshop,

ок, за case спасибо.

что касательно pre и post
нет в стандарте sql ни pre ни post
есть from clause, joined table, join condition
есть where clause, которая по определению логически выполняется после from clause,
но ни pre-condition, ни post-condition просто нет.

о pre и post отдельно от join condition можно говорить только применительно к алгоритмам работы конкретного оптимизатора.
Какое условие каким окажется - pre, формирующим derived table, к которой потом будет применяться join condition или уйдет на фазу post ("истинного" фильтра) - нельзя в общем предсказать даже видя конкретную запись запроса, т.к. it depends и от физики (наличия подходящих индексов, например или известных constraints) и от деталей устройства предиката и даже от фактических статистик, известных системе и оценки стоимости вычисления предиката. Для простых случаев - наверно достаточно надежно можно, в общем - нет.

Так или иначе, перенос чего-то в pre или наоборот - ранний join путем слияния явно выписанной derived table - оправдывается набором трансформаций/преобразований, который оптимизатор считает допустимыми, не меняющими логически результата запроса.
Все это здорово и правдоподобно, до тех пор, пока не примешивается data exception-s, которые подвешивают вопрос об эквивалентности результата.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319708
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousНикогда не говори "никогда"Зачет. :)
Пока шел на работу и думал про прядок еще возникла мысль про экзадату, когда писал ответ - вылетело из головы.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319737
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
boobyок, за case спасибо.Если глянуть в final query 10053, то думаю там можно увидеть lateral и соотвественно применив lateral/outer apply получить желаемое в 12с без всяких трюков. В 11g таки необходим case.
Необходимость case вообще снижается от версии к версии.
То есть, подмножество запросов когда возникает ORA-01719 на 11g меньше чем на 10g, а на 12с меньше чем на 11g.
И если в некоторых случаях необходимость case сомнительна, то в некоторых других - таки обязательна, иначе непонятно как трактовать одно из условий - фильтр или соединение.
Я вообще написал "работу" по соединениям примерно на 20 страниц - думаю в ближайший месяц опубликую.
Возможно кому-то будет полезно и/или интересно.
boobyчто касательно pre и postpre и post берут свое начало из уже упомянутой ноты "Guidelines for Using Outer Join Syntax (Doc ID 14736.1)".
Насколько помню первым начал применять эту терминологию на этом форуме Я и ёжик.
И она имеет отношение именно к Oracle native syntax и по понятным причинам не упоминается в стандарте.

Тут для полноты картины стоит отменить, что non-ANSI outer join поддерживал и MSSQL с давних времен.
Только там он называется " old-style, non-SQL-92-style join " (символы =* и *=).
Что еще раз подчеркивает то, что подобным образом пишут соединения не так как предписывает стандарт.
Майкрософт достаточно жестко выпиливает этот синтаксис и на последних версиях он сначала выдавал предупреждение, а потом и вовсе перестал поддерживаться.
Outer join operators *= and =* are not supported in 90 or later compatibility modes

В других ветках форума можно найти тоже достаточно много упоминаний про pre/post join, но там они по большей части этот концепт распиарен участником Добрый Э - Эх и его клонами. :)
...
Рейтинг: 0 / 0
10 сообщений из 35, страница 2 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Где лучше указывать условие, в join или where?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]