2013-08-20 2 views
0

У меня есть различные таблицы/представления, которые я тянущие от: Invoice, Detail, contact, party, address и remarks.Объединение двух таблиц без объединения столбцов

В принципе мне нужно вытащить данные из таблицы remarks и единственный способ, чтобы связать его с party стол, чтобы получить доступ к остальной части remarks таблицы для ссылки на его id столбец, который является внешним ключом на party столе.

id также колонка в Invoice зрения так, когда пункт FROM выполняет он сочетает в себе, что идентификаторы полей на Invoice стороне, и нет ничего, чтобы относиться к другим remarks столбцов. Кроме того, имена на колоннах либо таблицы не могут быть изменены:

SELECT * 
FROM Invoice as invoice_view LEFT OUTER JOIN 
    Detail as details ON invoice_view.transact = details.transact LEFT OUTER JOIN 
    contact AS co_contact ON invoice_view.company = co_contact.party LEFT OUTER JOIN 
    contact AS cp_contact ON invoice_view.company = cp_contact.party INNER JOIN 
    party as main_party ON invoice_view.party = main_party.party INNER JOIN 
    party as pay_party ON invoice_view.pay = pay_party.party INNER JOIN 
    party as rec_party ON invoice_view.rec = rec_party.party LEFT OUTER JOIN 

    contact as rec_contact ON rec_party.party = rec_contact.party INNER JOIN 
    address as rec_address ON rec_contact.party = rec_address.party AND rec_contact.address = rec_address.addresscode LEFT OUTER JOIN 
    contact AS pay_contact ON pay_party.party = pay_contact.party INNER JOIN 
    adddress AS pay_address ON pay_contact.party = pay_address.party AND pay_contact.address = pay_address.addresscode AND pay_party.party = pay_address.party LEFT OUTER JOIN 
--What I tried to get it working 
    remark as cp_remark CROSS JOIN 
party as custom_party 

WHERE 
    ( (custom_party.party = pay_party.party) AND (custom_party.id = cp_remark.id)    OR (cp_remark.id IS NULL) OR (custom_party.remark = 0)) 
--More where statements that have no affect on this 
+0

Так что все работает так, как должно быть, чтобы присоединиться к замечанию? – JsonStatham

+0

В чем вопрос? –

+1

Если вы измените select *, чтобы выбрать только нужные вам поля, проблема неоднозначных имен полей должна исчезнуть. –

ответ

3

Вы должны добавить ON состояния к вашему remark присоединиться и избавиться от этого CROSS JOIN. Например, вы могли бы сделать:

LEFT OUTER JOIN remark as cp_remark ON cp_remark.id = main_party.id OR cp_remark.id = pey_party.id OR cp_remark.id = rec_party.id  

На стороне записки, несколько рекомендаций:

  • Не используйте SELECT *, если вы пишете запрос для собственного потребления. Ваш код должен показывать вам, какие данные вы используете, только включите его в результирующий набор.
  • Это личное предпочтение, но я всегда считаю, что положить ваши соединения слева намного проще, чем поставить их справа.
  • Закажите ваш JOIN более логичным образом, ваш второй JOIN требует данных от вашего седьмого, попробуйте добавить детали по мере того, как вы идете.
  • Вы присоединяетесь слишком много таблиц, вам не нужно присоединяться ко всему, что имеет внешний ключ, а только данные, которые вы тянете для этого точного запроса.
  • Ваше окончательное соединение - полное соединение (нет ON), за которым следует CROSS JOIN (они эквивалентны), ни одна из них не является хорошей идеей в большинстве случаев. Оба эти результата приводят к полному результату добавления таблицы в результирующий набор.
  • Внешние ключи используются в качестве руководства и для целостности данных, они не определяют, как фактически выполняются соединения.
  • Аналогично названные столбцы можно разрешить с помощью table.column, которые вы уже делаете для своих объединений.

Так я бы отформатировал вашу оригинальную версию.(Так как я не знаю, какие именно изменения будут лучше для набора данных, я не включил мою рекомендацию для этого здесь)

SELECT * 
FROM Invoice as invoice_view 
LEFT OUTER JOIN Detail as details ON invoice_view.transact = details.transact 
INNER JOIN party as main_party ON invoice_view.party = main_party.party 
LEFT OUTER JOIN contact AS co_contact ON invoice_view.company = co_contact.party 
LEFT OUTER JOIN contact AS cp_contact ON invoice_view.company = cp_contact.party 

INNER JOIN party as rec_party ON invoice_view.rec = rec_party.party 
LEFT OUTER JOIN contact as rec_contact ON rec_party.party = rec_contact.party 
INNER JOIN address as rec_address ON rec_contact.party = rec_address.party 
           AND rec_contact.address = rec_address.addresscode 

INNER JOIN party as pay_party ON invoice_view.pay = pay_party.party 
LEFT OUTER JOIN contact AS pay_contact ON pay_party.party = pay_contact.party 
INNER JOIN adddress AS pay_address ON pay_contact.party = pay_address.party 
            AND pay_contact.address = pay_address.addresscode 
            AND pay_party.party = pay_address.party 
--What I tried to get it working        
LEFT OUTER JOIN remark as cp_remark 
CROSS JOIN party as custom_party 
WHERE 
((custom_party.party = pay_party.party) 
    AND (custom_party.id = cp_remark.id) 
    OR (cp_remark.id IS NULL) 
    OR (custom_party.remark = 0)) 
--More where statements that have no affect on this 

EDIT:

Поскольку вы спросили о том, что присоединяется сделать:

  • Регистрация/внутреннее соединение - принимать только те строки, которые имеют данные в обеих таблицах
  • левый Join/левое внешнее соединение - принимать только те строки, которые имеют данные в таблице слева (тот не указаны), брать данные из если имеется
  • право присоединиться/левый внешнее соединение - противоположное левое соединение (редко используется, так как левое соединение чаще используется)
  • внешнее соединение - данные в любом ряду создает данные на выходе
  • присоединиться без, как/перекрестное соединение - возвращение каждая комбинация строк между двумя столами

например:

Таблица A: 1,2,3,4
Таблица B: 5,6
перекрестное соединение A, B: (1, 5), (2,5), (3,5), (4,5), (1,6), (2,6), (3,6), (4,6)

Обратите внимание, что внутренние соединения начинаются как кросс-соединения, но ограничены положением ON. Это в основном способ задания условий соединения в более удобном месте (в соединении, а не в том месте). Внешние соединения могут быть концептуально считаны внутренними соединениями с пустой строкой, добавленной к необязательным таблицам (которая соответствует тому и только тогда, когда никакая другая строка не соответствует).

+2

Лично я нахожу, что я также делаю гораздо меньше ошибок, если сначала ставить внутренние соединения, а затем левое объединение, а затем крест. – HLGEM

+2

@HLGEM: Это правда, мне было трудно определить, что именно этот запрос искал, сгруппированный по назначению, был как можно более общим. В идеале вы начинаете с самых общих терминов, а затем заходите в более подробные сведения (что обычно следует за шаблоном, который вы упомянули). – Guvante

+0

, который был более ориентирован на ОП, чем вы. – HLGEM

Смежные вопросы