2009-01-12 14 views
40

Wikipedia stwierdza:Kiedy lub dlaczego używałbyś prawego połączenia zewnętrznego zamiast lewego?

"W praktyce bezpośrednie połączenia zewnętrzne są rzadko używane, ponieważ zawsze można je zastąpić lewymi złączeniami zewnętrznymi i nie zapewniają dodatkowej funkcjonalności."

Czy ktoś może zaproponować sytuację, w której wolałby korzystać z notacji PRAWA i dlaczego? Nie mogę wymyślić powodu, aby kiedykolwiek go użyć. Dla mnie nigdy nie uczyniłoby to bardziej zrozumiałym.

Edytuj: Jestem weteranem Oracle, który podejmuje noworoczną rezolucję, aby odzwyczaić się od składni (+). Chcę to zrobić dobrze

+1

Albo, innymi słowy, chcesz zrobić to na prawo i lewo (i pełne) :) –

Odpowiedz

27

Jedynym powodem, dla którego mogę użyć RIGHT OUTER JOIN, jest próba uczynienia twojego SQL'a bardziej samokomponującym.

Możliwe, że chcesz użyć lewych złączeń dla zapytań, które mają puste wiersze w zależności (wielu) stronach relacji jeden-do-wielu i prawych sprzężeń w tych zapytaniach, które generują puste wiersze po stronie niezależnej.

Może to również wystąpić w wygenerowanym kodzie lub jeśli wymagania kodowania sklepu określają kolejność deklaracji tabel w klauzuli FROM.

+2

+1, by zaakceptować odpowiedź, jeśli podsumować swoje, Michael i Iwana. – DCookie

+1

możemy uzyskać takie same wyniki, używając lewego sprzężenia zewnętrznego (przy okazji uzyskujemy prawe sprzężenie zewnętrzne) .Dlaczego więc istnieje opcja łączenia prawego lub odwrotnie? –

5

Jedyny raz, gdy pomyślę o prawym sprzężeniu zewnętrznym, to gdybym naprawiał pełne sprzężenie, a tak się złożyło, że potrzebowałem wyniku, aby zawierał wszystkie zapisy z tabeli po prawej stronie. Nawet tak leniwy jak ja, prawdopodobnie byłbym tak zirytowany, że przestawiłbym go na lewe sprzężenie.

Ten przykład z Wikipedia pokazuje co to znaczy:

SELECT * 
FROM employee 
    FULL OUTER JOIN department 
     ON employee.DepartmentID = department.DepartmentID 

Jeśli po prostu zastąpić słowo FULL z RIGHT masz nowe zapytanie, bez konieczności zamienić kolejność klauzuli ON.

+0

W jaki sposób instrukcja FULL dotarła na miejsce? Źle napisane mylące zapytanie? – dkretz

+3

'FULL' ma swój cel i nie zawsze wymaga" naprawy ", a zastąpienie go" RIGHT "nie robi tego samego. Co się stanie, jeśli tworzysz raport, który pomoże firmie zatwierdzić zadania dla pracowników i departamentów i chcesz uwzględnić działy, które nie zatrudniają pracowników, a także pracowników, którzy nie zostali przypisani do działu? – utexaspunk

1

Instrukcje SQL, oprócz tego, że są poprawne, powinny być tak łatwe do odczytania i wyraziście zwięzłe, jak to tylko możliwe (ponieważ reprezentują pojedyncze działania atomowe, a twój umysł musi je całkowicie zignorować, aby uniknąć niezamierzonych konsekwencji). Czasami wyrażenie jest wyraźniej zaznaczone prawym złączem zewnętrznym.

Ale zawsze można przekształcić się w drugi, a optymalizator będzie działał tak samo jak drugi.

Od dłuższego czasu co najmniej jeden z głównych produktów rdbms obsługuje tylko LEFT OUTER JOIN. (Wierzę, że to MySQL).

+1

"Czasami wyrażenie jest wyraźniej zaznaczone prawym złączem zewnętrznym". Walczę, kiedy to może być. Po co używać składni, która jest zasadniczo odwrotnością innej, częściej używanej? Czy masz przykład? – DCookie

+1

Nie. Nigdy nie używałam RIGHT OUTER JOIN sam: D. – dkretz

7

B RIGHT JOIN A jest taka sama, jak LEFT JOIN B

B PRAWO przyłączyć się czyta: B na prawo, potem ŁĄCZY A. oznacza, że ​​A jest w lewym boku zbiór danych. tak samo, jak LEWEJ DOŁĄCZU B

Brak wydajności, którą można uzyskać, jeśli przestawisz LEWY POŁĄCZENIA na PRAWE.

Jedyne powody, dla których mogę pomyśleć, dlaczego użyć RIGHT JOIN, to jeśli jesteś typem osoby, która lubi myśleć od środka (wybierz * z prawej strony z prawej strony nagłówka). To tak, jak inni, tacy jak little-endian, inni tacy jak big-endian, inni lubią top down design, inni lubią bottom-up design.

Drugą z nich jest, jeśli masz już ogromne zapytanie, w którym chcesz dodać kolejną tabelę, gdy jest to ból w szyi, aby zmienić kolejność zapytania, więc po prostu podłącz tabelę do istniejącej kwerendy za pomocą RIGHT JOIN.

+0

+1, zaakceptuje odpowiedź, jeśli podsumuje twoje, Jekke i Ivan. – DCookie

2
SELECT * FROM table1 [BLANK] OUTER JOIN table2 ON table1.col = table2.col 

zastąp [Puste] z:

lewy - jeśli chcesz, aby wszystkie rekordy z Tabela1, nawet jeśli nie mają one kol pasujący Table2'S (Są także Table2 rekordy z meczów)

PRAWO - jeśli chcesz, aby wszystkie rekordy z Table2 nawet jeśli nie mają one kol pasujący tabela1'S (wliczone są również zapisy z meczów Tabela 1)

Full - jeśli chcesz, aby wszystkie rekordy z tabela1 iz Table2

O czym wszyscy mówią? Są takie same? Nie sądzę.

+2

Zawsze można zastąpić DOŁĄCZ DO PRAWYM ZEWNĘTRZNYM za pomocą LEWEGO ZŁĄCZA ZEWNĘTRZNEGO, które daje taką samą odpowiedź i na odwrót. – DCookie

+0

Masz na myśli, że po prostu wymieniasz słowa "LEWE" i "PRAWE", czy też masz na myśli flop wokół składni zapytania? –

+3

musisz również zmienić kolejność tabel w złączeniu. – HLGEM

2

Jedyny raz, kiedy użyłem prawostronnego łączenia, było, gdy chcę spojrzeć na dwa zbiory danych i już mam połączenia w określonej kolejności dla lewego lub wewnętrznego sprzężenia z wcześniej napisanego zapytania. W tym przypadku, powiedzmy, że chcesz widzieć jako jeden zestaw danych rekordy nie zawarte w tabeli a, ale w tabeli b, a w innym zestawie rekordów nie w tabeli b, ale w tabeli a. Nawet wtedy robię to tylko po to, by zaoszczędzić czas na przeprowadzaniu badań, ale zmienię go, gdyby był to kod uruchamiany więcej niż jeden raz.

2
SELECT * FROM table_a 
INNER JOIN table_b ON .... 
RIGHT JOIN table_c ON .... 

Jak inaczej można szybko/łatwo wewnętrzna przyłączyć pierwszych 2 stoliki i połączyć z table_c zapewniając jednocześnie wszystkie wiersze w table_c zawsze wybiera?

+5

Możesz wyświetlić najpierw table_c i lewo, aby dołączyć do innych. – DCookie

+0

Pisząc go, @ składnia Matta wydaje się bardziej czytelny niż równowartość: 'SELECT * FROM table_c LEFT JOIN (SELECT * FROM table_a INNER JOIN table_b dalej .... ) ON .... ' – 8forty

14

Nigdy wcześniej nie używałam right join i nigdy nie pomyślałam, że mogę go potrzebować, i wydaje mi się to trochę nienaturalne. Ale po tym, jak o tym myślał, to może być bardzo przydatna w sytuacji, gdy trzeba zewnętrzna dołączyć jedną tabelę z przecięciu wielu tabelach, więc trzeba tabele tak:

enter image description here

i chcesz uzyskać prowadzić tak:

enter image description here

Albo w SQL (MS SQL Server):

declare @temp_a table (id int) 
declare @temp_b table (id int) 
declare @temp_c table (id int) 
declare @temp_d table (id int) 

insert into @temp_a 
select 1 union all 
select 2 union all 
select 3 union all 
select 4 

insert into @temp_b 
select 2 union all 
select 3 union all 
select 5 

insert into @temp_c 
select 1 union all 
select 2 union all 
select 4 

insert into @temp_d 
select id from @temp_a 
union 
select id from @temp_b 
union 
select id from @temp_c 

select * 
from @temp_a as a 
    inner join @temp_b as b on b.id = a.id 
    inner join @temp_c as c on c.id = a.id 
    right outer join @temp_d as d on d.id = a.id 

id   id   id   id 
----------- ----------- ----------- ----------- 
NULL  NULL  NULL  1 
2   2   2   2 
NULL  NULL  NULL  3 
NULL  NULL  NULL  4 
NULL  NULL  NULL  5 

Jeśli więc przełączysz się na left join, wyniki nie będą takie same.

select * 
from @temp_d as d 
    left outer join @temp_a as a on a.id = d.id 
    left outer join @temp_b as b on b.id = d.id 
    left outer join @temp_c as c on c.id = d.id 

id   id   id   id 
----------- ----------- ----------- ----------- 
1   1   NULL  1 
2   2   2   2 
3   3   3   NULL 
4   4   NULL  4 
5   NULL  5   NULL 

Jedynym sposobem, aby to zrobić bez prawa sprzężenia jest użycie wspólnego wyrażenia stołowego lub podzapytanie

select * 
from @temp_d as d 
    left outer join (
     select * 
     from @temp_a as a 
      inner join @temp_b as b on b.id = a.id 
      inner join @temp_c as c on c.id = a.id 
    ) as q on ... 
+4

You nie musisz zagnieżdżać SELECT, zamiast tego możesz zagnieździć join: 'FROM @temp_d JAK LEWE ZEWNĘTRZNE DOŁĄCZ (temp_a JAKO WEJŚCIE WEWNĘTRZNE @temp_b AS b ON b.id = a.id WEJŚCIE WEWNĘTRZNE @temp_c AS c ON c.id = a.id) NA a.id = d.id'. (Nawiasy są niepotrzebne, są dodawane tylko dla czytelności). To prawda, że ​​są ludzie, którzy są niezdecydowani, do jakiej składni bardziej się brzydzą, zagnieżdżone sprzężenia lub prawe zewnętrzne sprzężenia, więc możliwe, że prawe sprzężenia mogą działać * mniej źle * dla nich. :) –

+0

Miło, nigdy nie użyłem składni zagnieżdżonych połączeń również :) –

2

ja nie miałem już naprawdę dużo do myślenia na prawo przyłączyć, ale przypuszczam, że ja nie od prawie 20 lat pisania zapytań SQL, trafiają na uzasadnienie ich używania. Z pewnością widziałem wiele z nich, które domyślam się wynikać z miejsca, w którym programiści korzystali z wbudowanych generatorów zapytań.

Ilekroć się zetknąłem, przepisałem zapytanie, aby je wyeliminować. Stwierdziłem, że po prostu wymagają zbyt wiele dodatkowej energii mentalnej, aby się uczyć lub ponownie się uczyć, jeśli nie odwiedziłeś zapytania przez jakiś czas. i nierzadko zdarza się, że zapytanie zagubiło się lub zwróciło nieprawidłowe wyniki - i to zwykle ta nieprawidłowość spowodowała, że ​​poprosiłem mnie o sprawdzenie, dlaczego zapytania nie działały.

Myśląc o tym, po wprowadzeniu prawa-złączenia, masz teraz to, co uważałbym za konkurencyjne gałęzie logiki, które muszą spotkać się w środku. Jeśli zostaną wprowadzone dodatkowe wymagania/warunki, obie te gałęzie mogą być dalej rozszerzane, a Ty masz teraz więcej złożoności, którą musisz żonglować, aby upewnić się, że jedna gałąź nie daje nieprawidłowych wyników.

Ponadto, po wprowadzeniu łączenia prawego, inni mniej doświadczeni programiści, którzy później pracują nad zapytaniem, mogą po prostu przymocować dodatkowe tabele do prawej części zapytania, a tym samym rozszerzyć konkurencyjne przepływy logiczne, które wciąż występują. trzeba się spotkać w środku; lub w niektórych przypadkach widziałem, zacznij zagnieżdżać widoki, ponieważ nie chcą dotykać oryginalnej logiki, być może po części dlatego, że mogą nie rozumieć zapytania lub reguł biznesowych, które były na miejscu, które doprowadziły do ​​logiki.

0

W niektórych bazach danych SQL znajdują się wskazówki dotyczące optymalizatora, które informują optymalizatora o dołączeniu do tabel w kolejności, w jakiej występują w klauzuli FROM - np. /*+ORDERED */ w Oracle. W niektórych prostych implementacjach może to być nawet jedyny dostępny plan wykonania.

W takich przypadkach kolejność tabel w klauzuli FROM ma znaczenie, więc może być przydatna RIGHT JOIN.

0

Myślę, że to trudne, jeśli nie masz prawa dołączyć w tym przypadku. ex z oracle.

with a as(
    select 1 id, 'a' name from dual union all 
    select 2 id, 'b' name from dual union all 
    select 3 id, 'c' name from dual union all 
    select 4 id, 'd' name from dual union all 
    select 5 id, 'e' name from dual union all 
    select 6 id, 'f' name from dual 
), bx as(
    select 1 id, 'fa' f from dual union all 
    select 3 id, 'fb' f from dual union all 
    select 6 id, 'f' f from dual union all 
    select 6 id, 'fc' f from dual 
) 
select a.*, b.f, x.f 
from a left join bx b on a.id = b.id 
right join bx x on a.id = x.id 
order by a.id 
+0

'wybierz a. *, Bf, xf od bx x lewe sprzężenie zewnętrzne a na a.id = x.id lewe sprzężenie bx b na b.id = a .id porządek przez a.id' – JohnLBevan

Powiązane problemy