Rodzaje złączeń

Iloczyn kartezjański

  • generuje zestaw danych poprzez złączenie danych w relacji z tą samą relacją
SELECT table1.column, table2.column
FROM table1, table2;

SELECT table1.column, table2.column
FROM table1 CROSS JOIN table2;

Zazwyczaj użycie czystego iloczynu kartezjańskiego jest uznawane za błąd (i takie ostrzeżenie generuje). Jeżeli na pewno chcemy użyć iloczynu kartezjańskiego, warto użyć polecenia z drugiego przykładu.

SELECT last_name, department_name
FROM employees
CROSS JOIN departments;

Powyższy przykład jest w pewnym sensie - bez sensu: generuje zestaw każdy pracownik - każdy departament, co biznesowo nie ma sensu.

Iloczyn kartezjański powstaje, gdy warunek połączenia zostanie pominięty lub jest błędny (w sensie logicznym), lub wszystkie krotki relacji zostały połączone z krotkami kolejnej relacji. Aby mu zapobiec, zawsze należy używać warunków połączenia.

Połączenia równowartościowe

Zadanie polegające na znalezieniu dla każdego pracownika nazwy jego działu można rozwiązać za pomocą tzw. połączenia równowartościowego. Ważne jest, aby warunki połączeniowe porównywały jedynie wartości atrybutów pochodzących z łączonych relacji, i za pomocą operatora =.

SELECT employees.employee_id, employees.department_id, departments.department_name
FROM employees, departments
WHERE employees.department_id = departments.department_id

Nazwy atrybutów, według których łączymy, są takie same w obu relacjach. Wykorzystujemy przeto mechanizm prefiksów (prefiks = nazwa relacji) - zapobiega to niejasności składni zapytania.

Połączenie naturalne

{T1} NATURAL JOIN {T2}

Połączenie jest dokonywane "automatycznie", ponieważ warunek równości dotyczy wszystkich par atrybutów o takich samych nazwach. W wyniku połączenia naturalnego atrybut(y) występują w wyniku tylko raz. Jeśli te same nazwy będą wskazywać różne typy (dziedziny), zostanie zwrócony błąd).

SELECT department_id, department_name, location_id, city
FROM departments NATURAL JOIN locations;

Połączenie równowartościowe z wykorzystaniem klauzuli ON

{T1} JOIN {T2} ON search_condition
SELECT e.employee_id, e.last_name, e.department_id, d.department_id, d.location_id
FROM employees e JOIN departments d ON e.department_id = d.department_id;

Aliasy kolumn

Możemy wykorzystać aliasy, aby uniknąć przepisywania prefiksów kolumn. Są one opcjonalne i najczęściej składają się z jednej - dwóch liter (maksymalnie 30). Skraca to zapis i zapobiega niejednoznaczności bardziej skomplikowanych zapytań. Użycie aliasu wyłącza możliwość użycia nazwy tabeli.

Klauzula USING

{T1} JOIN {T2} USING join_column_list

Jeżeli wiele atrybutów posiada identyczną nazwę, ale różne dziedziny, klauzula NATURAL JOIN może zostać zastąpiona klauzulą USING. Nie należy używać nazw tabel lub aliasów podczas odwoływania się do kolumn użytych w sekcji USING.

SELECT e.employee_id, e.last_name, d.location_id, department_id
FROM employees e JOIN departments
USING department_id;

Klauzula NATURAL JOIN a USING

Róznica polega na tym, że pierwsza notacja automatycznie wymaga, aby wszystkie pary atrybutów o tych samych nazwach w obu łączonych relacjach były tego samego typu.

Różnica między połączeniem naturalnym i równowartościowym

W wyniku połączenia naturalnego atrybut połączeniowy występuje tylko raz. W wyniku połączenia równowartościowego występują oba atrybuty.

SELECT * FROM pracownicy NATURAL JOIN zespoly;
SELECT * FROM pracownicy JOIN zespoly USING id_zesp;


SELECT * FROM pracownicy JOIN zespoly ON pracownicy.id_zesp = zespoly.id_zesp;

Złączenie zwrotne

Specjalny przypadek, w którym tabelę łączymy samą z sobą. Może to być dowolny typ połączenia (wewnętrzne, zewnętrzne, równościowe, nierównościowe), za wyjątkiem połączenia naturalnego (bo nic nie zwróci). Składnia jest taka sama, jedyną różnicą jest tutaj podanie takiej samej nazwy relacji po obu stronach operatora definiującego połączenie.

Złączenie zwrotne z wykorzystaniem klauzuli ON

SELECT e.last_name "EMP", m.last_name "MNGR"
FROM employees e JOIN employees m
    ON e.manager_id = m.employee_id;

Łączenie wielu tabel

Ponieważ wynik łączenia jest relacją, nic nie stoi na przeszkodzie, aby tworzyć jej połączenia z kolejną relacją. W ten sposób można wykonywać dowolną liczbę połączeń.

Łączenie wielu tabel z wykorzystaniem klauzuli ON

SELECT employee_id, city, department_name
FROM employees e
    JOIN departments d ON d.department_id = e.department_id
    JOIN locations l ON d.location_id = l.location_id;

Dla każdego połączenia definiowany jest warunek połączenia (wyjątek: iloczyn kartezjański, NATURAL JOIN). Ponieważ jest o jedno mniej połączenie niż łączonych relacji, tyle też należy zdefiniować warunków połączeniowych. Ważne też jest to, że operator połączenia jest łączny lewostronnie, chociaż priorytet można zmieniać za pomocą nawiasów.

Połączenia nierównowartościowe

Połączenia, w których warunek połączenia nie używa operatora równości, lecz dowolny inny operator. Podobnie jak wcześniej, powstanie relacja, która zawiera wszystkie atrybuty z obu relacji. Krotki są tworzone również w podobny sposób.

Operatory: >, >=, <, <=, != (<>), LIKE, BETWEEN.

Przykład: niech tabela employees zawiera nazwiska i płace, a job_grades - przedziały płac i nazwy tych przedziałów.

SELECT e.last_name, e.salary, j.grade_level
FROM employees e
    JOIN job_grades j ON e.salary BETWEWN j.lowest_sal AND j.highest_sal;

Jeżeliby przedziały nachodziły na siebie, w wyniku tego zapytania dany pracownik mógłby zostać wyświetlony kilka razy.

Połączenia zewnętrzne

Dotychczas omawialiśmy połączenia wewnętrzne, ponieważ efektem powstającej relacji są te krotki, które spełniały warunki połączenia. Istnieją również połączenia zewnętrzne, które mogą zawierać niedopasowane krotki, nazywane połączeniami zewnętrznymi lewo(prawo)stronnymi (pełnymi).

SELECT table1.column, table2.column
FROM table1
[LEFT|RIGHT|FULL OUTER JOIN table 2 ON table1.column_name = table2.column_name];

Przykład: czy istnieją pracownicy niebędący w departamentach? czy istnieją departamenty bez pracowników?

SELECT e.last_name, e.department_id, d.department_name
FROM employees e
    LEFT OUTER JOIN departments d ON e.department_id = d.department_id;
SELECT e.last_name, e.department_id, d.department_name
FROM employees e
    RIGHT OUTER JOIN departments d ON e.department_id = d.department_id;
SELECT e.last_name, e.department_id, d.department_name
FROM employees e
    FULL OUTER JOIN departments d ON e.department_id = d.department_id;

 

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.