Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Про (+) объясните?  [new]
Соединитель
Guest
Делаем запрос:
WITH a AS
     (SELECT 1 ID FROM DUAL
      UNION ALL
      SELECT 2    FROM DUAL
      UNION ALL
      SELECT 3    FROM DUAL
      UNION ALL
      SELECT 4    FROM DUAL
      UNION ALL
      SELECT 5    FROM DUAL), b AS
                   (SELECT 1 ID FROM DUAL
                    UNION ALL
                    SELECT 2    FROM DUAL
                    UNION ALL
                    SELECT 3    FROM DUAL)
SELECT a.ID aid, b.ID bid
  FROM a a, b b
 WHERE ( b.ID = 1  OR b.ID IS NULL ) AND a.ID = b.ID(+)

Результат
1 1
4
5
то есть получили outer join. Но ведь условие b.ID = 1 без плюса.
Вопрос это фича такая?
22 июн 06, 15:57    [2802898]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
SeaGate
Member

Откуда: Новосибирск
Сообщений: 1635
Соединитель
Делаем запрос:
WITH a AS
     (SELECT 1 ID FROM DUAL
      UNION ALL
      SELECT 2    FROM DUAL
      UNION ALL
      SELECT 3    FROM DUAL
      UNION ALL
      SELECT 4    FROM DUAL
      UNION ALL
      SELECT 5    FROM DUAL), b AS
                   (SELECT 1 ID FROM DUAL
                    UNION ALL
                    SELECT 2    FROM DUAL
                    UNION ALL
                    SELECT 3    FROM DUAL)
SELECT a.ID aid, b.ID bid
  FROM a a, b b
 WHERE ( b.ID = 1  OR b.ID IS NULL ) AND a.ID = b.ID(+)

Результат
1 1
4
5
то есть получили outer join. Но ведь условие b.ID = 1 без плюса.
Вопрос это фича такая?

Во первых, если я правильно понял, может это:
OR b.ID IS NULL
Во вторых, а что хотели получить то?
22 июн 06, 16:05    [2802958]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116242
Соединитель
Делаем запрос:
WITH a AS
     (SELECT 1 ID FROM DUAL
      UNION ALL
      SELECT 2    FROM DUAL
      UNION ALL
      SELECT 3    FROM DUAL
      UNION ALL
      SELECT 4    FROM DUAL
      UNION ALL
      SELECT 5    FROM DUAL), b AS
                   (SELECT 1 ID FROM DUAL
                    UNION ALL
                    SELECT 2    FROM DUAL
                    UNION ALL
                    SELECT 3    FROM DUAL)
SELECT a.ID aid, b.ID bid
  FROM a a, b b
 WHERE ( b.ID = 1  OR b.ID IS NULL ) AND a.ID = b.ID(+)

Результат
1 1
4
5
то есть получили outer join. Но ведь условие b.ID = 1 без плюса.
Вопрос это фича такая?

Ну можно и так сказать :)
В таблице b есть строка с ID = 1 и по ней идет соединение. Остальные две строки появляются по условию OR b.id is NULL.
ИМХО достаточно написать вместо ( b.ID = 1 OR b.ID IS NULL )
b.id (+) = 1 - это эквивалентно.
22 июн 06, 16:06    [2802971]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
VladIg
Member

Откуда: Краснодар
Сообщений: 152
Сработали условия
WHERE ( b.ID = 1 OR b.ID IS NULL ) AND a.ID = b.ID(+)
С точки зрения булевой алгебры все корректно. А условие b.ID = 1 в случае OR не обязательно.
22 июн 06, 16:06    [2802972]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
Жара
Guest
dmidek
Ну можно и так сказать :)
В таблице b есть строка с ID = 1 и по ней идет соединение. Остальные две строки появляются по условию OR b.id is NULL.
ИМХО достаточно написать вместо ( b.ID = 1 OR b.ID IS NULL )
b.id (+) = 1 - это эквивалентно.

В Дортмунде сегодня жарко? :)
22 июн 06, 16:09    [2802997]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
Соединитель
Guest
Да, с условием or b.id is null можно писать любое другое на таблицу b и будет outer join. Вопрос в том что в доке:
If the WHERE clause contains a condition that compares a column from table B with a constant, then the (+) operator must be applied to the column so that Oracle returns the rows from table A for which it has generated nulls for this column. Otherwise Oracle will return only the results of a simple join.

то есть должно быть inner join. Это баг, фича ?????
22 июн 06, 16:09    [2803000]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
SeaGate
Member

Откуда: Новосибирск
Сообщений: 1635
dmidek
ИМХО достаточно написать вместо ( b.ID = 1 OR b.ID IS NULL )
b.id (+) = 1 - это эквивалентно.

Не совсем, если Вы об этом:
SQL> WITH a AS
  2       (SELECT 1 ID FROM DUAL
  3        UNION ALL
  4        SELECT 2    FROM DUAL
  5        UNION ALL
  6        SELECT 3    FROM DUAL
  7        UNION ALL
  8        SELECT 4    FROM DUAL
  9        UNION ALL
 10        SELECT 5    FROM DUAL), b AS
 11                     (SELECT 1 ID FROM DUAL
 12                      UNION ALL
 13                      SELECT 2    FROM DUAL
 14                      UNION ALL
 15                      SELECT 3    FROM DUAL)
 16  SELECT a.ID aid, b.ID bid
 17    FROM a a, b b
 18   WHERE a.ID = b.ID(+) and b.id(+)=1
 19  /

       AID        BID
---------- ----------
         1          1
         2 
         3 
         4 
         5 
22 июн 06, 16:10    [2803003]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116242
Жара
dmidek
Ну можно и так сказать :)
В таблице b есть строка с ID = 1 и по ней идет соединение. Остальные две строки появляются по условию OR b.id is NULL.
ИМХО достаточно написать вместо ( b.ID = 1 OR b.ID IS NULL )
b.id (+) = 1 - это эквивалентно.

В Дортмунде сегодня жарко? :)

И хотелось бы сказать, что да, но погода очень приятная
22 июн 06, 16:20    [2803076]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
SeaGate
Member

Откуда: Новосибирск
Сообщений: 1635
Соединитель
то есть должно быть inner join. Это баг, фича ?????

Если посмотрите план запроса, то сначала Oracle выполняет внешнее соединение, а только потом налагает filter по (b.id=1 or b.id is null).
И null не константа, я так думаю.
22 июн 06, 16:24    [2803111]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116242
Вторая попытка.
Давайте сначала выполним Ваш запрос только с outer join

WITH a AS
         (SELECT 1 ID FROM DUAL
          UNION ALL
          SELECT 2    FROM DUAL
          UNION ALL
          SELECT 3    FROM DUAL
          UNION ALL
          SELECT 4    FROM DUAL
          UNION ALL
         SELECT 5    FROM DUAL), b AS
                      (SELECT 1 ID FROM DUAL
                       UNION ALL
                       SELECT 2    FROM DUAL
                       UNION ALL
                       SELECT 3    FROM DUAL)
  SELECT a.ID aid, b.ID bid
  FROM a a, b b
 WHERE --( b.ID = 1  OR b.ID IS NULL ) AND 
 a.ID = b.ID(+)
/
AID	BID
1	1
2	2
3	3
5	
4	
Ну вот, а теперь посмотрите на Ваше условие.
( b.ID = 1 OR b.ID IS NULL )
По первому условию в OR проходит первая строка, в по второму - четвертая
и пятая.
22 июн 06, 16:27    [2803129]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
Соединитель
Guest
Более того фактически снимается ограничение на использование (+) в выражении OR
WITH a AS
     (SELECT 1 ID FROM DUAL
      UNION ALL
      SELECT 2   FROM DUAL
      UNION ALL
      SELECT 3  FROM DUAL
      UNION ALL
      SELECT 4  FROM DUAL
      UNION ALL
      SELECT 5  FROM DUAL), b AS
                   (SELECT 1 ID FROM DUAL
                    UNION ALL
                    SELECT 2  FROM DUAL
                    UNION ALL
                    SELECT 3   FROM DUAL)
SELECT a.ID aid, b.ID bid
  FROM a a, b b
 WHERE ( a.id = 1 or b.id = 2 OR b.id IS NULL ) AND a.ID = b.ID(+)

вопрос поэтому и возник - можно пользоваться или в других версиях к примеру запрос рухнет. (У меня 9.2.0.7)

Результат
1 1
2 2
4
5
22 июн 06, 16:28    [2803137]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
SeaGate
Member

Откуда: Новосибирск
Сообщений: 1635
http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96540/queries7.htm#2054014
In addition to join conditions, the WHERE clause of a join query can also contain other conditions that refer to columns of only one table. These conditions can further restrict the rows returned by the join query.

Т.е. документальное подтверждение того, что сначало join затем другие из where clause
22 июн 06, 16:36    [2803195]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
Goldminer
Member

Откуда:
Сообщений: 553
Соединитель

вопрос поэтому и возник - можно пользоваться или в других версиях к примеру запрос рухнет. (У меня 9.2.0.7)

Не рухнет. Результат совершенно законный. ИМХО, ЛОГИЧЕСКИ всегда необходимо различать JOIN и WHERE, как это сделано в ANSI SQL, в Oracle же просто исторически сложилось, что СИНТАКСИЧЕСКИ то и другое было свалено в WHERE, причем для OUTER JOIN пришлось изгольнуться и придумать (+).
ЗЫ: А (+) с константой вообще от лукавого (ИМХО).
22 июн 06, 16:58    [2803361]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
Я и ёжик
Member

Откуда: СПб
Сообщений: 1815
SeaGate

Т.е. документальное подтверждение того, что сначало join затем другие из where clause


Metalink Subject: Guidelines for Using Outer Join Syntax
Doc ID: Note:14736.1

Ключевые слова Post-Join Predicates и Pre-Join Predicates (+)
22 июн 06, 18:26    [2803864]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
SeaGate
Member

Откуда: Новосибирск
Сообщений: 1635
Я и ёжик
Metalink Subject: Guidelines for Using Outer Join Syntax
Doc ID: Note:14736.1

Ключевые слова Post-Join Predicates и Pre-Join Predicates (+)

Простите, но не дают мне доступ на Metalink, все обещают и обещают...
Нельзя ли кратко изложить суть данной notes?
23 июн 06, 06:02    [2804574]     Ответить | Цитировать Сообщить модератору
 Re: Про (+) объясните?  [new]
Я и ёжик
Member

Откуда: СПб
Сообщений: 1815
Суть ноты следует из названия.

А то, на что я хотел обратить внимание, это порядок применения предикатов
при внешнем соединении оформленном через (+).
Предикаты помеченные (+) вычесляются (извлекаются) до того как производится соединение ( Pre-Join Predicates ), т.е. до того как соответствующему столбцу будет присвоено значение NULL если не найдена присоеденяемая запись. Предикаты внешне присоеденямой таблицы НЕ помеченные (+) вычисляются после выплнения соеденения (Post-Join Predicates), т.е. когда присвоены null столбцам внешнеприсоединяемой таблицы для строк которым не нашлось соответствия.

Если с этой точки зрения посмотреть на приводимые здесь примеры, все становится прозрачно.
Условия ( b.ID = 1 OR b.ID IS NULL ) это Post-Join Predicates, b.id в этот момент уже имеет значение NULL (для строк которым не нашлась пара) соответственно срабатывает условие b.ID IS NULL.
23 июн 06, 10:12    [2804992]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить