Подтвердить что ты не робот

Внутреннее соединение и внешнее соединение; это порядок таблиц из важного?

Почему порядок таблиц важен при объединении внешнего и внутреннего соединений? следующее с ошибками:

SELECT grp.number AS number,     
       tags.value AS tag   
FROM groups grp,
     insrel archiverel  
LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber   
WHERE archiverel.snumber = 11128188 AND    
      archiverel.dnumber = grp.number 

с результатом:

ERROR:  invalid reference to FROM-clause entry for table "grp" LINE 5: LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.d... 
^ HINT:  There is an entry for table "grp", but it cannot be referenced from this part of the query.

когда группы отменяются в FROM, все работает:

SELECT  grp.number AS number,     
        tags.value AS tag   
FROM    insrel archiverel,
        groups grp
LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber   
WHERE   archiverel.snumber = 11128188 AND    
        archiverel.dnumber = grp.number 
4b9b3361

Ответ 1

Я считаю, что вы можете думать об этом как о проблеме приоритета оператора.

Когда вы пишете это:

FROM groups grp,
     insrel archiverel  
LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber   

Я думаю, что это интерпретируется синтаксическим анализатором следующим образом:

FROM groups grp,
(
  (
     insrel archiverel  
     LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
  )
LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber
)

Если это так, то в самом внутреннем соединении "grp" несвязано.

Когда вы меняете строки с "группами" и "insrel", самое внутреннее соединение применяется к "группам" и "ownrel", поэтому оно работает.

Вероятно, это тоже сработало бы:

    FROM groups grp
         JOIN insrel archiverel  ON archiverel.dnumber = grp.number
    LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
    LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber 
WHERE archiverel.snumber = 11128188

Ответ 2

Я не думаю, что кто-то совсем прибил это или объяснил это очень хорошо. Вы объединяете "старый стиль" (тета) и "новый стиль" (ANSI), которые, как я подозреваю, группируются так, как вы этого не ожидаете. Посмотрите на это следующим образом:

SELECT * FROM a, b JOIN c ON a.x = c.x

это как сказать

SELECT * FROM a, (b JOIN c on a.x = c.x)

где заключенная в скобки вещь представляет собой кучу таблиц, объединенных в одну виртуальную таблицу, которая должна быть объединена с тета-объединением против 'a'. Очевидно, что таблица "a" не может быть частью соединения, поскольку она только соединяется позже. Переверните его, и вы делаете

SELECT * FROM b, (a JOIN c on a.x = c.x)

что совершенно понятно и так прекрасно. Я не уверен, почему вы не используете синтаксис ANSI для всего этого, хотя, кажется немного странным (и жестоким для человека, который должен его поддерживать!)

Ответ 3

Поскольку в первом grp не является частью объединения, предложение ON принадлежит.

Ответ 4

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

SELECT grp.number AS number,     
       tags.value AS tag   
FROM groups grp
JOIN insrel archiverel ON archiverel.dnumber = grp.number
LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber   
WHERE archiverel.snumber = 11128188

Мне было бы интересно узнать больше, если поведение по дизайну.

Ответ 5

Для внутреннего соединения порядок таблиц не важен.

Для внешнего соединения это так. Все строки из таблицы со стороны, указанной (это ЛЕВЫЙ или ПРАВЫЙ), будут включены, в то время как только строки, соответствующие критериям соединения, будут включены из таблицы с другой стороны.

Поскольку OUTER JOINS содержат все строки с одной стороны, они, как говорят, увеличивают набор результатов. INNER JOINS содержат только строки с обеих сторон, если они совпадают, поэтому они говорят (в общем), чтобы уменьшить наборы результатов. Таким образом, вы, как правило, хотите делать свои INNER JOINS перед ВЗАИМОДЕЙСТВИЯМИ (когда это возможно).

В вашем случае это почти наверняка результат злого синтаксиса A, B.