powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Где лучше указывать условие, в join или where?
35 сообщений из 35, показаны все 2 страниц
Где лучше указывать условие, в join или where?
    #39318958
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сразу оговорюсь, что речь исключительно про inner join.
Нужно связать две таблицы по ключу (типу) и из полученного результата выбрать строки с определенным статусом.
Какой вариант лучше?
Этот:
Код: plsql
1.
2.
3.
4.
select *
from t1
join t2 on (t2.type_id = t1.type_id)
where t2.status > 0


или этот:
Код: plsql
1.
2.
3.
select *
from t1
join t2 on (t2.type_id = t1.type_id and t2.status > 0)


?
На форумах встречал точку зрения, что нужно придерживаться семантики — в JOIN указывать условия для связывания и выбора данных, а в WHERE указывать условия для фильтрации данных, и с этой точки зрения первый вариант предпочтительнее и логичнее.
Но на тех же форумах встречал и другую точку зрения, что WHERE применяется уже после того, как соединения и строки были выбраны, поэтому лучше использовать второй вариант.


________________________
Мы смотрим с оптимизмом...
...в оптический прицел.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39318959
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Но на тех же форумах встречал и другую точку зрения, что WHERE применяется уже после того,
как соединения и строки были выбраны

Никогда больше не ходи на форумы, где ты увидел этот бред.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39318964
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я как бы не на одном форуме это увидел.
Я гуглил по запросу «oracle condition where vs join» и подобная точка зрения встречалась на разных ресурсах.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39318977
проходил мимо...
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Какой вариант лучше?
План смотрел? А чего тогда спрашиваешь?
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319011
Dimitry SibiryakovНикогда больше не ходи на форумы
достаточно, чтобы он не писал на этом.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319024
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Я как бы не на одном форуме это увидел.
Вот ни на один из них и не ходи.

Alibek B. подобная точка зрения встречалась на разных ресурсах.
Теперь у тебя есть список ресурсов, написанное на которых не стоит гроша выеденного.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319032
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.На форумах встречал точку зрения, что нужно придерживаться семантики — в JOIN указывать условия для связывания и выбора данных, а в WHERE указывать условия для фильтрации данных, и с этой точки зрения первый вариант предпочтительнее и логичнее.


Вот это правильно.

Alibek B.Но на тех же форумах встречал и другую точку зрения, что WHERE применяется уже после того, как соединения и строки были выбраны, поэтому лучше использовать второй вариант.


А вот то или бред или ты чего-то недопонял. WHERE применяется "уже после того" при outer join а с inner join все в кучу а уж потом оптимайзер решит в каком порядке.

SY.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319076
Фотография AlexFF__|
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYА вот то или бред или ты чего-то недопонял. WHERE применяется "уже после того" при outer join...
Ну как только рука поднимается такое писать?
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319106
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexFF__|SYА вот то или бред или ты чего-то недопонял. WHERE применяется "уже после того" при outer join...
Ну как только рука поднимается такое писать?

Для особо продвинутых:

Код: 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.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
SQL> select  dname,
  2          ename,
  3          sal
  4    from      dept d
  5          left join
  6              emp e
  7            on    e.deptno = d.deptno
  8               and
  9                  sal > 4000
 10  /

DNAME          ENAME                                 SAL
-------------- ------------------------------ ----------
ACCOUNTING     KING                                 5000
RESEARCH
SALES
OPERATIONS

SQL> select  dname,
  2          ename,
  3          sal
  4    from      dept d
  5          left join
  6              emp e
  7            on    e.deptno = d.deptno
  8    where sal > 4000
  9  /

DNAME          ENAME                                 SAL
-------------- ------------------------------ ----------
ACCOUNTING     KING                                 5000

SQL> select  dname,
  2          ename,
  3          sal
  4    from      dept d
  5          left join
  6              emp e
  7            on    e.deptno = d.deptno
  8               and
  9                  sal > 10000
 10  /

DNAME          ENAME                                 SAL
-------------- ------------------------------ ----------
ACCOUNTING
RESEARCH
SALES
OPERATIONS

SQL> select  dname,
  2          ename,
  3          sal
  4    from      dept d
  5          left join
  6              emp e
  7            on    e.deptno = d.deptno
  8    where sal > 10000
  9  /

no rows selected

SQL>



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

Код: sql
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.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
SQL> select  dname,
  2          ename,
  3          sal
  4    from      dept d
  5          left join
  6              emp e
  7            on     e.deptno = d.deptno
  8               and
  9                   d.deptno = 10
 10  /

DNAME          ENAME                                 SAL
-------------- ------------------------------ ----------
ACCOUNTING     CLARK                                2450
ACCOUNTING     KING                                 5000
ACCOUNTING     MILLER                               1300
OPERATIONS
SALES
RESEARCH

6 rows selected.

SQL> select  dname,
  2          ename,
  3          sal
  4    from      dept d
  5          left join
  6              emp e
  7            on    e.deptno = d.deptno
  8    where d.deptno = 10
  9  /

DNAME          ENAME                                 SAL
-------------- ------------------------------ ----------
ACCOUNTING     CLARK                                2450
ACCOUNTING     KING                                 5000
ACCOUNTING     MILLER                               1300

SQL>



А таперичи посмотрим как Oracle расширяет оба SQL:

Код: 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.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
SQL> set long 10000
SQL> variable c clob
SQL> begin
  2      dbms_utility.expand_sql_text('select  dname,
  3          ename,
  4          sal
  5    from      dept d
  6          left join
  7              emp e
  8            on     e.deptno = d.deptno
  9               and
 10                   d.deptno = 10',:c);
 11  end;
 12  /

PL/SQL procedure successfully completed.

SQL> print c

C
--------------------------------------------------------------------------------
SELECT  "A1"."DNAME_1" "DNAME",
        "A1"."ENAME_2" "ENAME",
        "A1"."SAL_3" "SAL"
  FROM  (
         SELECT  "A3"."DEPTNO" "QCSJ_C000000000300000",
                 "A3"."DNAME" "DNAME_1",
                 "A2"."ENAME""ENAME_2",
                 "A2"."SAL" "SAL_3",
                 "A2"."DEPTNO" "QCSJ_C000000000300001"
           FROM  "SCOTT"."DEPT" "A3",
                 "SCOTT"."EMP" "A2"
           WHERE "A2"."DEPTNO"(+) = "A3"."DEPTNO"
             AND "A3"."DEPTNO"= CASE
                                  WHEN ("A2"."DEPTNO"(+) IS NOT NULL) THEN 10
                                  ELSE 10
                                END
        ) "A1"


SQL> begin
  2      dbms_utility.expand_sql_text('select  dname,
  3          ename,
  4          sal
  5    from      dept d
  6          left join
  7              emp e
  8            on    e.deptno = d.deptno
  9    where d.deptno = 10',:c);
 10  end;
 11  /

PL/SQL procedure successfully completed.

SQL> print c

C
--------------------------------------------------------------------------------
SELECT  "A1"."DNAME_1" "DNAME",
        "A1"."ENAME_2" "ENAME",
        "A1"."SAL_3" "SAL"
  FROM  (
         SELECT  "A3"."DEPTNO" "QCSJ_C000000000300000_0",
                 "A3"."DNAME" "DNAME_1",
                 "A2"."ENAME" "ENAME_2",
                 "A2"."SAL" "SAL_3",
                 "A2"."DEPTNO" "QCSJ_C000000000300001"
           FROM  "SCOTT"."DEPT" "A3",
                 "SCOTT"."EMP" "A2"
           WHERE "A2"."DEPTNO"(+) = "A3"."DEPTNO"
        ) "A1"
  WHERE "A1"."QCSJ_C000000000300000_0" = 10

SQL>



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

Достаточно только одного примера:
Код: plsql
1.
2.
3.
4.
select  *
     from dept d
     left join emp e on e.deptno = d.deptno
       where d.любое_поле = :1


Потом смотрим:
SYWHERE применяется "уже после того" при outer join...
Ты также продолжишь утверждать, что сначала join потом where?
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319131
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexFF__|Ты также продолжишь утверждать, что сначала join потом where?

Да. Это ANSI правило. И оптимайзер руководствуясь этим решаем можно ли все до кучи или нет. Например:

Код: plsql
1.
2.
3.
4.
5.
select  dname,ename
     from dept d
     left join emp e on e.deptno = d.deptno
       where e.ename = 'AlexFF__|'
/



Тут можно все до кучи и это видно по:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
begin
    dbms_utility.expand_sql_text('select  dname,ename
     from dept d
     left join emp e on e.deptno = d.deptno
       where e.ename = ''AlexFF__|''',:c);
end;
/
print c
SELECT  "A1"."DNAME_1" "DNAME",
        "A1"."ENAME_2" "ENAME"
  FROM  (
         SELECT  "A3"."DEPTNO" "QCSJ_C000000000300000",
                 "A3"."DNAME" "DNAME_1",
                 "A2"."ENAME" "ENAME_2",
                 "A2"."DEPTNO" "QCSJ_C000000000300001"
           FROM  "SCOTT"."DEPT" "A3",
                 "SCOTT"."EMP" "A2"
           WHERE "A2"."DEPTNO"="A3"."DEPTNO"
        ) "A1"
  WHERE "A1"."ENAME_2"='AlexFF__|'



Оптимайзер даже поменял outer на inner join. А вот тут нельзя до кучи:

Код: plsql
1.
2.
3.
4.
5.
select  dname,ename
     from dept d
     left join emp e on e.deptno = d.deptno
       where d.loc = 'AlexFF__|'
/



Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
begin
    dbms_utility.expand_sql_text('select  dname,ename
     from dept d
     left join emp e on e.deptno = d.deptno
       where d.loc = ''AlexFF__|''',:c);
end;
/
print c
SELECT  "A1"."DNAME_1" "DNAME",
        "A1"."ENAME_3" "ENAME"
  FROM  (
         SELECT  "A3"."DEPTNO" "QCSJ_C000000000300000",
                 "A3"."DNAME" "DNAME_1",
                 "A3"."LOC" "LOC_2",
                 "A2"."ENAME" "ENAME_3",
                 "A2"."DEPTNO" "QCSJ_C000000000300001"
           FROM  "SCOTT"."DEPT" "A3",
                 "SCOTT"."EMP" "A2"
           WHERE "A2"."DEPTNO"(+)="A3"."DEPTNO"
        ) "A1"
  WHERE "A1"."LOC_2"='AlexFF__|'



Но это все об оптимайзере. А я о прогрaммисте который должен понимать что логически сначала join а уж потом filter (ибо фильтруем результат) и при outer join прописка условия в ON или в WHERE может кардинально повлиять на результат.

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

Кстати, даже при native outer join Oracle делит предикаты WHERE на join conditions и filter conditions. Почитай Guidelines for Using Outer Join Syntax (Doc ID 14736.1) где четко расписан порядок действий (логический) и последним шагом является "Rows that do not pass the non-outer join predicates are removed". А non-outer join predicates и есть по сути ANSIшный WHERE ну и outer join predicates есть ANSIшный ON.

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

Если б where с предикатом по внутренней таблице применялось после, то следующий запрос валился бы с ошибкой.
Код: plsql
1.
2.
3.
4.
select *
from (select rownum id from dual connect by rownum <= 3) t1
left join (select rownum id from dual connect by rownum <= 3) t2 on t1.id = t2.id and 1/(t1.id-2) > 0
where t1.id <> 2;

На металинке неплохое объяснение про pre/post предикаты, но там во всех предикатах фигурирует внешняя таблица.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319166
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshopSY,

Если б where с предикатом по внутренней таблице применялось после, то следующий запрос валился бы с ошибкой.


Опять 25. Я говoрю про правила а ты про имплементацию. Посмотри на:

Код: 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.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
SQL> begin
  2      dbms_utility.expand_sql_text('select *
  3  from (select rownum id from dual connect by rownum <= 3) t1
  4  left join (select rownum id from dual connect by rownum <= 3) t2 on t1.id = t2.id and 1/(t1.id-2) > 0
  5  where t1.id <> 2',:c);
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL> print c

C
--------------------------------------------------------------------------------
SELECT  "A1"."ID_0" "ID",
        "A1"."ID_1" "ID"
  FROM  (
         SELECT  "A3"."ID" "ID_0",
                 "A2"."ID" "ID_1"
           FROM  (
                  SELECT  ROWNUM "ID"
                    FROM  "SYS"."DUAL" "A4"
                    CONNECT BY ROWNUM<=3
                 ) "A3",
                 (
                  SELECT  ROWNUM "ID"
                    FROM  "SYS"."DUAL" "A5"
                    CONNECT BY ROWNUM<=3
                 ) "A2"
           WHERE "A3"."ID" = "A2"."ID"(+)
             AND 1/("A3"."ID"-2) > CASE
                                     WHEN ("A2"."ID"(+) IS NOT NULL) THEN 0
                                     ELSE 0
                                   END
        ) "A1"
  WHERE "A1"."ID_0"<>2



Ведь все расписaно - inline view делает left join a main select фильтрует результат left join'a. Ну а дальше оптимизатор колдует как эту логику оптимальней выполнить и понимает что оптимальней сначала отфильтровать левую тaблицу. Как результат, ZERODIVIDE не выскакивает. Тот-же результaт мы имеем при WHERE условие1 AND условие2 когда, например одно из них FALSE а другое вызывает ZERODIVIDE. Вот в каком порядке оптимайзер решит их выполнить зависит получим ли мы ZERODIVIDE или нет.

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

SY.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319172
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYОпять 25. Я говoрю про правила а ты про имплементацию.Когда я пытался говорить про логический порядок (правила) - набежало экспертов по имплементации. :) 16016806
SYSQL стандарт четко разгранивает условия соединения и условия фильтрации и прямо говорит - сначала соединяем а потом фильтруемБыл бы благодарен за указание где об этом сказано в стандарте SQL:2003 .

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

Если ты ищешь что-то типа фразы "сначала join а потом where", то ничего не найдешь. Стандарт это язык определений и связей между ними. Открываем например ANSI/ISO/IEC International Standard (IS) Database Language SQL — Part 2: Foundation (SQL/Foundation) «Part 2» . Смотрим определение where clause:


7.8 <where clause>

Format
<where clause> ::= WHERE <search condition>

Syntax Rules
1) Let T be the result of the preceding <from clause>. Each column reference directly contained in
the <search condition> shall unambiguously reference a column of T or be an outer reference.


Смотрим определение <from clause>:


7.5 <from clause>

Format
<from clause> ::=
FROM <table reference list>
<table reference list> ::=
<table reference> [ { <comma> <table reference> }... ]


Смотрим определение <table reference>:

7.6 <table reference>

Function
Reference a table.
Format
<table reference> ::=
<table primary>
| <joined table>


Смотрим определение <joined table>:

7.7 <joined table>

Function
Specify a table derived from a Cartesian product, inner or outer join, or union join.
Format
<joined table> ::=
<cross join>
| <qualified join>
| <natural join>
| <union join>
<cross join> ::=
<table reference> CROSS JOIN <table primary>
<qualified join> ::=
<table reference> [ <join type> ] JOIN <table reference>
<join specification>
<natural join> ::=
<table reference> NATURAL [ <join type> ] JOIN <table primary>
<union join> ::=
<table reference> UNION JOIN <table primary>
<join specification> ::=
<join condition>
| <named columns join>
<join condition> ::= ON <search condition>
<named columns join> ::=
USING <left paren> <join column list> <right paren>
<join type> ::=
INNER
| <outer join type> [ OUTER ]
<outer join type> ::=
LEFT
| RIGHT
| FULL
<join column list> ::= <column name list>


То есть WHERE clause применяется к результату предшествующей FROM clause котoрая в свою очередь есть либо физическая таблица либо таблица полученная (derived) путем соединения (join) таблиц. То есть сначала join а потом WHERE.

SY.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319193
Фотография AlexFF__|
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYДа. Это ANSI правило. И оптимайзер руководствуясь этим решаем можно ли все до кучи или нет. Например:
............................................................
Но это все об оптимайзере. А я о прогрaммисте который должен понимать что логически сначала join а уж потом filter (ибо фильтруем результат) и при outer join прописка условия в ON или в WHERE может кардинально повлиять на результат.
SY.
Причем тут правила и примеры с expand_sql_text, показывающие запрос на входе построителя планов?
Ты рассказываешь топикстартеру по сферического коня в вакууме, который будет только полезен при писании рефератов студентам.
Что толку от теории логического порядка, если у ТС сейчас создается впечатление, что его предположение правильно?
Alibek B.Но на тех же форумах встречал и другую точку зрения, что WHERE применяется уже после того, как соединения и строки были выбраны, поэтому лучше использовать второй вариант.
Это форум oracle, тут людей интересует, как ты писал, имплементация .
Так что извини, но мне кажется, что ты путаешь не только ТС, но и, учитывая твой статус, многих других интересующих.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319195
Высокие материи. Влияние логического порядка на производительность, подкрепленные частными вариантами планов.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319198
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYТо есть WHERE clause применяется к результату предшествующей FROM clause

В данном случае она "предшествует" чисто синтаксически. То есть выделенное предложение
говорит, что WHERE в тексте запроса стоит после FROM и ничего больше.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319230
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovSYТо есть WHERE clause применяется к результату предшествующей FROM clause

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

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

То, что в частных конкретных случаях (включая innser join) фильтры могут без нарушения логики быть протолкнуты непосредственно к rowsource - не меняет принципа.
Логически предикаты where применяются к множеству, определенному from.
Точка.
Если начинающий программист будет воспринимать это именно так - не допустит дурацких ошибок, которыми бывает пересыпан код начинающих, не осознающих разницы.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319231
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovSYТо есть WHERE clause применяется к результату предшествующей FROM clause

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


Смотрим определение where clause:


7.8 <where clause>

Syntax Rules
1) Let T be the result of the preceding <from clause>. Each column reference directly contained in
the <search condition> shall unambiguously reference a column of T or be an outer reference.

General Rules
1) The <search condition> is applied to each row of T. The result of the <where clause> is a table
of those rows of T for which the result of the <search condition> is true.


То есть General Rules прямо говорит что WHERE применяется к T а T есть результат FROM а FROM есть либо таблица либо их соединение (joned table) а их соединение имеет только ON clause и никаких WHERE.

SY.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319340
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous...
То, что в частных конкретных случаях (включая innser join) фильтры могут без нарушения логики быть протолкнуты ...
не меняет принципа.
...
вот это и есть главный вопрос трансформации - допустимо ли "проталкивать" t1.id <> 2, в условиях, когда внешнее соединение соединение ожидается по условию 1/(t1.id-2) > 0
Эквивалентен ли результат запроса, который должен давать ошибку на этапе построения соединения, запросу, возвращающему набор данных без ошибок.
Даваемый конкретной реализацией ответ - эквивалентен, так как "проталкивание" произошло.
Требуется объяснить эквивалентность без нарушения логики.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319341
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexFF__|Это форум oracle, тут людей интересует, как ты писал, имплементация .
Так что извини, но мне кажется, что ты путаешь не только ТС, но и, учитывая твой статус, многих других интересующих.

Боюсь что путаешь ты сам себя. Открою тебе страшный секрет - имплементации, как таковой, нет. Есть имплементация каждой отдельно взятой версии. Сегодня так а завтра уже чуть-чуть не так. И имплементация эта нигде не документировaна и "изучаема" она чисто эмпирически. Изучать имплементацию нужно с точки зрения тюнинга но, IMHO, не более и пoсле того как четко изучил стандарт ибо не зная что должно быть на выходе невозможно оценить имплементацию. И повторюсь eсть имплементация каждой отдельно взятой версии. Поэтому перезд на новую версию всегда более или менее pain in the but.

SY.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в join или where?
    #39319343
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
boobyвот это и есть главный вопрос трансформации - допустимо ли "проталкивать" t1.id <> 2, в условиях, когда внешнее соединение соединение ожидается по условию 1/(t1.id-2) > 0
Эквивалентен ли результат запроса, который должен давать ошибку на этапе построения соединения, запросу, возвращающему набор данных без ошибок.
То есть по основному вопросу - о том, что предикаты where относятся к множеству, определенному from, возражений нет.
Ок, давайте теперь рассмотрим вопрос о предикате 1/(t1.id-2) > 0.
Теоретически:
Предикат описывает множество, для которого указанное выражение истинно .
Ничего другого он не описывает.
Вопрос "истинно ли выражение 1/(t1.id-2) > 0 для t1.id = 2" определяет, входит указанная строка в множество или нет.
То, что значение выражения не определено для t1.id = 2 в рамках трехзначной логики означает, что выражение не истинно и строка во множество, определенное предикатом, не входит.
Таким образом, тезис, о том, что SQL-запрос "ДОЛЖЕН давать ошибку" в указанной ситуации - на самом деле ложен, выбрасывание исключения "деление на 0" следует отнести скорее к особенностям реализации , а фильтр "t1.id <> 2" можно считать (теоретически) не влияющим на результат, поскольку записи с t1.id = 2 не является элементом множества, отвечающего предикату "1/(t1.id-2) > 0".

Практически:
Все мы знаем, что вычисление значения выражения по сокращенному пути (short circuit evaluation) может давать тот же эффект в отношении исключительных ситуаций в императивных языках, в т.ч. в PL/SQL. И, будучи должным образом документировано, такое поведение никого это не парит.
Почему подобное поведение должно беспокоить в декларативном SQL, для которого вообще не имеет смысла само понятие exception (ну нет в ЯЗЫКЕ SQL средств для работы с исключительными ситуациями)?
Беспокоить может лишь нестабильность результата (то набор данных, то аварийное завершение в зависимости от положения звезд на небе) - и подобное поведение (if any) мы смело запишем в недостатки конкретной реализации.

Вот как-то так.
...
Рейтинг: 0 / 0
Где лучше указывать условие, в 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
35 сообщений из 35, показаны все 2 страниц
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Где лучше указывать условие, в join или where?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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