Добавление левого соединения уменьшает количество возвращаемых строк.

Я пытаюсь отладить следующий фрагмент SQL, последний сегмент которого представляет собой левое соединение. Когда я запускаю запрос ниже, я получаю 8 строк, но если я удаляю последнее левое соединение, я получаю 13 результатов. Насколько я понимаю, левое соединение никогда не должно уменьшать количество возвращаемых строк, как это возможно?

SELECT  *
  FROM
(
  SELECT   A.QUESTIONNAIRE_ID,
      D.QUESTION_ANSWER_ID   ,
      D.QUESTION_REPLICA_ID
    FROM ADMINISTRATIONS A,
      ADMINISTRATION_DETAILS D
    WHERE A.ADMINISTRATION_ID = 4326509
      AND A.ADMINISTRATION_ID =D.ADMINISTRATION_ID
)
T
  JOIN QUESTION_ANSWERS QA
  ON QA.QUESTION_ANSWER_ID=T.QUESTION_ANSWER_ID
  JOIN QUESTIONS Q
  ON Q.QUESTION_ID=QA.QUESTION_ID
  JOIN ANSWERS A
  ON A.ANSWER_ID=QA.ANSWER_ID
  JOIN PHRASES PA
  ON PA.PHRASE_ID=A.PHRASE_ID
  JOIN QUESTIONNAIRE_DETAILS QD
  ON QD.QUESTIONNAIRE_ID      = T.QUESTIONNAIRE_ID
    AND QD.QUESTION_ID        =QA.QUESTION_ID
    AND QD.QUESTION_REPLICA_ID=1
  LEFT JOIN QUESTIONNAIRE_DETAILS D
  ON D.QUESTIONNAIRE_ID      = T.QUESTIONNAIRE_ID
    AND D.QUESTION_ID        =QA.QUESTION_ID
    AND D.QUESTION_REPLICA_ID=T.QUESTION_REPLICA_ID
  LEFT JOIN ANSWER_VALUES AV
  ON AV.QUESTIONNAIRE_ID=T.QUESTIONNAIRE_ID
    AND AV.QUESTION_ID  =QA.QUESTION_ID
    AND AV.ANSWER_ID    =QA.ANSWER_ID
  LEFT JOIN ADMINISTRATION_DETAILS AD
  ON AD.ADMINISTRATION_ID     =4326509
    AND AD.QUESTION_ANSWER_ID =T.QUESTION_ANSWER_ID
    AND AD.QUESTION_REPLICA_ID=T.QUESTION_REPLICA_ID
  LEFT JOIN ADMINISTRATION_OPEN_ANSWERS O
  ON O.ADMINISTRATION_ID     =AD.ADMINISTRATION_ID
    AND O.QUESTION_ANSWER_ID =AD.QUESTION_ANSWER_ID
    AND O.QUESTION_REPLICA_ID=AD.QUESTION_REPLICA_ID
  LEFT JOIN --the offending left join that causes me to get 8 results instead of 13
    (
      SELECT 1 AS destination_id FROM dual
    )
    RD
  ON RD.DESTINATION_ID       = 0
    AND O.QUESTION_ANSWER_ID = 1328 --If I remove just this line, I get 13 results
    ;

Похоже, что происходит принудительная проверка, когда удаляются строки без записей в таблице O, но я не могу найти документацию, объясняющую это как ожидаемое поведение.

Я использую Oracle Database 12c Release 12.1.0.1.0 — 64-битное производство.


person Jordan Bentley    schedule 07.08.2014    source источник
comment
Вы удаляете только одну строку или все left join?   -  person Gordon Linoff    schedule 08.08.2014
comment
что произойдет, если вы SELECT 0 AS destination_id FROM dual вместо 1?   -  person Paul Maxwell    schedule 08.08.2014
comment
@GordonLinoff, выполняющий любую операцию, возвращает правильное количество строк, даже если левое соединение даже не соответствует ни одной из строк в моих данных.   -  person Jordan Bentley    schedule 08.08.2014


Ответы (1)


Похоже это баг оптимизатора, если я его откачу с помощью

ALTER SESSION SET optimizer_features_enable='11.2.0.4';

он начинает вести себя правильно.

Изменить: вот более постоянное решение:

CREATE OR REPLACE TRIGGER revert_optimizer AFTER LOGON ON DATABASE
  DECLARE
    CMD VARCHAR2(100) := 'alter session set optimizer_features_enable="11.2.0.4"';
  BEGIN
    EXECUTE IMMEDIATE CMD;
  END revert_optimizer;
person Jordan Bentley    schedule 07.08.2014