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

Несколько левых объединений на нескольких таблицах в одном запросе

У меня есть одна таблица master, в которой есть элементы, хранящиеся на нескольких уровнях, родители и дочерние элементы, и есть вторая таблица, которая может иметь или не иметь дополнительных данных. Мне нужно запросить два уровня из моей основной таблицы и иметь левое соединение на моей второй таблице, но из-за заказа в моем запросе это не сработает.

SELECT something FROM master as parent, master as child
  LEFT JOIN second as parentdata ON parent.secondary_id = parentdata.id
  LEFT JOIN second as childdata ON child.secondary_id = childdata.id
WHERE parent.id = child.parent_id AND parent.parent_id = 'rootID'

Левое соединение работает только с последней таблицей в предложении from, поэтому я могу только заставить ее работать для одного из левых объединений. В приведенном выше примере ни одно из левых соединений не будет работать, потому что первые левые точки присоединения к первой таблице в предложении from, второй никогда не будет работать так.

Как я могу сделать эту работу?

4b9b3361

Ответ 1

Этот тип запроса должен работать - после переписывания с явным синтаксисом JOIN:

SELECT something
FROM   master      parent
JOIN   master      child ON child.parent_id = parent.id
LEFT   JOIN second parentdata ON parentdata.id = parent.secondary_id
LEFT   JOIN second childdata ON childdata.id = child.secondary_id
WHERE  parent.parent_id = 'rootID'

Срабатывание здесь заключается в том, что явный JOIN связывает перед "старым стилем" CROSS JOIN запятую (,). Я цитирую руководство здесь:

В любом случае JOIN связывается более плотно, чем запятые, разделяющие FROM -list предметов.

После переписывания первого все объединения применяются слева направо (по логике - Postgres может свободно переставлять таблицы в плане запроса в противном случае), и это работает.

Просто чтобы выразить свою точку зрения, это тоже сработает:

SELECT something
FROM   master parent
LEFT   JOIN second parentdata ON parentdata.id = parent.secondary_id
,      master child
LEFT   JOIN second childdata ON childdata.id = child.secondary_id
WHERE  child.parent_id = parent.id
AND    parent.parent_id = 'rootID'

Но явный синтаксис JOIN, как правило, предпочтительнее, как показывает ваш случай еще раз.

И помните, что несколько (LEFT) JOIN могут умножать строки:

Ответ 2

Вы можете сделать это следующим образом:

SELECT something
FROM
    (a LEFT JOIN b ON a.a_id = b.b_id) LEFT JOIN c on a.a_aid = c.c_id
WHERE a.parent_id = 'rootID'

Ответ 3

Операторы JOIN также являются частью предложения FROM, более формально join_type используется для объединения двух from_item в один from_item, несколько из которых затем могут формировать список, разделенный запятыми, после FROM. См. http://www.postgresql.org/docs/9.1/static/sql-select.html.

Итак, прямое решение вашей проблемы:

SELECT something
FROM
    master as parent LEFT JOIN second as parentdata
        ON parent.secondary_id = parentdata.id,
    master as child LEFT JOIN second as childdata
        ON child.secondary_id = childdata.id
WHERE parent.id = child.parent_id AND parent.parent_id = 'rootID'

Лучшим вариантом было бы использовать только JOIN, как уже было предложено.