PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Używanie złączeń do łączenia danych z różnych tabel w PostgreSQL


Wprowadzenie

Podział powiązanych danych na osobne tabele może być korzystny z punktu widzenia spójności, elastyczności i niektórych rodzajów wydajności. Jednak nadal potrzebujesz rozsądnego sposobu ponownej integracji rekordów, gdy odpowiednie informacje obejmują wiele tabel.

W relacyjnych bazach danych połączenia oferują sposób łączenia rekordów w co najmniej dwóch tabelach na podstawie wspólnych wartości pól. Różne typy sprzężeń mogą osiągać różne wyniki w zależności od sposobu obsługi niedopasowanych wierszy. W tym przewodniku omówimy różne typy złączeń oferowanych przez PostgreSQL oraz sposoby ich wykorzystania do łączenia danych tabel z wielu źródeł.



Co to są połączenia?

Krótko mówiąc, dołącza to sposób wyświetlania danych z wielu tabel. Robią to, łącząc ze sobą rekordy z różnych źródeł na podstawie pasujących wartości w określonych kolumnach. Każdy wynikowy wiersz składa się z rekordu z pierwszej tabeli połączonego z wierszem z drugiej tabeli, w oparciu o jedną lub więcej kolumn w każdej tabeli o tej samej wartości.

Podstawowa składnia złączenia wygląda tak:

SELECT    *FROM    <first_table><join_type> <second_table>    <join_condition>;

W sprzężeniu każdy wynikowy wiersz jest tworzony przez uwzględnienie wszystkich kolumn z pierwszej tabeli, po których następują wszystkie kolumny z drugiej tabeli. SELECT część zapytania może być użyta do określenia dokładnych kolumn, które chcesz wyświetlić.

Z oryginalnych tabel można utworzyć wiele wierszy, jeśli wartości w kolumnach użytych do porównania nie są unikatowe. Na przykład wyobraź sobie, że porównywana jest kolumna z pierwszej tabeli, która zawiera dwa rekordy o wartości „czerwony”. Dopasowana z tym jest kolumna z drugiej tabeli, która ma trzy wiersze z tą wartością. Połączenie wygeneruje sześć różnych wierszy dla tej wartości, reprezentujących różne kombinacje, które można osiągnąć.

Typ sprzężenia i warunki sprzężenia określają sposób konstrukcji każdego wyświetlanego wiersza. Ma to wpływ na to, co dzieje się z wierszami z każdej tabeli, które działają i nie mieć dopasowanie pod warunkiem dołączenia.

Ze względu na wygodę wiele złączeń dopasowuje klucz podstawowy w jednej tabeli do skojarzonego klucza obcego w drugiej tabeli. Chociaż klucze podstawowe i obce są używane tylko przez system bazy danych do zachowania gwarancji spójności, ich relacja często czyni z nich dobrego kandydata na warunki łączenia.



Różne typy złączeń

Dostępne są różne typy złączeń, z których każde potencjalnie da różne wyniki. Zrozumienie, jak skonstruowany jest każdy typ, pomoże ci określić, który jest odpowiedni dla różnych scenariuszy.


Złączenie wewnętrzne

Domyślne połączenie nazywa się sprzężeniem wewnętrznym . W PostgreSQL można to określić za pomocą INNER JOIN lub po prostu JOIN .

Oto typowy przykład demonstrujący składnię sprzężenia wewnętrznego:

SELECT    *FROM    table_1[INNER] JOIN table_2    ON table_1.id = table_2.table_1_id;

Sprzężenie wewnętrzne jest najbardziej restrykcyjnym typem sprzężenia, ponieważ wyświetla tylko wiersze utworzone przez łączenie wierszy z każdej tabeli. Wszelkie wiersze w tabelach składowych, które nie mają pasującego odpowiednika w drugiej tabeli, są usuwane z wyników. Na przykład, jeśli pierwsza tabela ma wartość „niebieski” w kolumnie porównania, a druga tabela nie ma rekordu o tej wartości, ten wiersz zostanie pominięty w danych wyjściowych.

Jeśli przedstawisz wyniki jako diagram Venna tabel komponentów, sprzężenie wewnętrzne umożliwi przedstawienie nakładającego się obszaru dwóch okręgów. Żadna z wartości, które istniały tylko w jednej z tabel, nie jest wyświetlana.



Połączenie lewe

Łączenie lewe to łączenie, które pokazuje wszystkie rekordy znalezione w łączeniu wewnętrznym oraz wszystkie niedopasowane wiersze z pierwszej tabeli. W PostgreSQL można to określić jako LEFT OUTER JOIN lub jako po prostu LEFT JOIN .

Podstawowa składnia lewego sprzężenia jest zgodna z następującym wzorcem:

SELECT    *FROM    table_1LEFT JOIN table_2    ON table_1.id = table_2.table_1_id;

Sprzężenie lewostronne jest konstruowane przez wykonanie sprzężenia wewnętrznego w celu skonstruowania wierszy ze wszystkich pasujących rekordów w obu tabelach. Następnie uwzględniane są również niedopasowane rekordy z pierwszej tabeli. Ponieważ każdy wiersz w łączeniu zawiera kolumny obu tabel, niedopasowane kolumny mają wartość NULL jako wartość dla wszystkich kolumn w drugiej tabeli.

Jeśli przedstawisz wyniki jako diagram Venna tabel komponentów, lewe sprzężenie pozwoli ci przedstawić cały lewy okrąg. Części lewego okręgu reprezentowane przez przecięcie między dwoma okręgami będą miały dodatkowe dane uzupełnione o prawą tabelę.



Prawe połączenie

Złączenie prawe to złączenie, które pokazuje wszystkie rekordy znalezione w złączeniu wewnętrznym oraz wszystkie niedopasowane wiersze z drugiej tabeli. W PostgreSQL można to określić jako RIGHT OUTER JOIN lub jako po prostu RIGHT JOIN .

Podstawowa składnia prawego sprzężenia jest zgodna z następującym wzorcem:

SELECT    *FROM    table_1RIGHT JOIN table_2    ON table_1.id = table_2.table_1_id;

Prawe sprzężenie jest konstruowane przez wykonanie sprzężenia wewnętrznego w celu skonstruowania wierszy ze wszystkich pasujących rekordów w obu tabelach. Następnie uwzględniane są również niedopasowane rekordy z drugiej tabeli. Ponieważ każdy wiersz w łączeniu zawiera kolumny obu tabel, niedopasowane kolumny mają wartość NULL jako wartość dla wszystkich kolumn w pierwszej tabeli.

Jeśli przedstawisz wyniki jako diagram Venna tabel komponentów, prawe sprzężenie pozwoli ci przedstawić cały prawy okrąg. Części prawego okręgu reprezentowane przez przecięcie dwóch okręgów będą miały dodatkowe dane uzupełnione o lewą tabelę.



Pełne połączenie

Łączenie pełne to łączenie, które pokazuje wszystkie rekordy znalezione w łączeniu wewnętrznym oraz wszystkie niedopasowane wiersze z obu tabel składowych. W PostgreSQL można to określić jako FULL OUTER JOIN lub jako po prostu FULL JOIN .

Podstawowa składnia pełnego sprzężenia jest zgodna z następującym wzorcem:

SELECT    *FROM    table_1FULL JOIN table_2    ON table_1.id = table_2.table_1_id;

Pełne sprzężenie jest konstruowane przez wykonanie sprzężenia wewnętrznego w celu skonstruowania wierszy ze wszystkich pasujących rekordów w obu tabelach. Następnie uwzględniane są również niedopasowane rekordy z obu tabel. Ponieważ każdy wiersz w łączeniu zawiera kolumny obu tabel, niedopasowane kolumny mają wartość NULL jako wartość dla wszystkich kolumn w niedopasowanej innej tabeli.

Jeśli przedstawisz wyniki jako diagram Venna tabel komponentów, pełne sprzężenie pozwoli ci całkowicie przedstawić oba okręgi komponentów. Przecięcie dwóch okręgów będzie miało wartości dostarczone przez każdą z tabel składowych. Części okręgów poza nakładającym się obszarem będą miały wartości z tabeli, do której należą, używając NULL aby wypełnić kolumny znajdujące się w drugiej tabeli.



Połączenie krzyżowe

Specjalne złącze zwane CROSS JOIN jest również dostępny. Sprzężenie krzyżowe nie używa żadnych porównań w celu określenia, czy wiersze w każdej tabeli pasują do siebie. Zamiast tego wyniki są konstruowane przez proste dodanie każdego wiersza z pierwszej tabeli do każdego wiersza drugiej tabeli.

Daje to iloczyn kartezjański wierszy w dwóch lub więcej tabelach. W efekcie ten styl łączenia bezwarunkowo łączy wiersze z każdej tabeli. Tak więc, jeśli każda tabela ma trzy wiersze, wynikowa tabela będzie miała dziewięć wierszy zawierających wszystkie kolumny z obu tabel.

Na przykład, jeśli masz tabelę o nazwie t1 w połączeniu z tabelą o nazwie t2 , każdy z wierszami r1 , r2 i r3 , wynik będzie składał się z dziewięciu wierszy połączonych w następujący sposób:

t1.r1 + t2.r1t1.r1 + t2.r2t1.r1 + t2.r3t1.r2 + t2.r1t1.r2 + t2.r2t1.r2 + t2.r3t1.r3 + t2.r1t1.r3 + t2.r2t1.r3 + t2.r3


Self-join

Sprzężenie własne to dowolne sprzężenie, które łączy ze sobą wiersze tabeli. Może nie być od razu oczywiste, w jaki sposób może to być przydatne, ale w rzeczywistości ma wiele typowych zastosowań.

Często tabele opisują jednostki, które mogą pełnić wiele ról względem siebie. Na przykład, jeśli masz tabelę people , każdy wiersz może potencjalnie zawierać mother kolumna odwołująca się do innych people na stole. Samodzielne łączenie pozwoliłoby połączyć ze sobą te różne wiersze, łącząc drugą instancję tabeli z pierwszą, w której te wartości pasują.

Ponieważ sprzężenia własne odwołują się do tej samej tabeli dwukrotnie, aliasy tabeli są wymagane do ujednoznacznienia odwołań. Na przykład w powyższym przykładzie możesz dołączyć do dwóch wystąpień people tabela używająca aliasów people AS children i people AS mothers . W ten sposób możesz określić, do której instancji tabeli odwołujesz się podczas definiowania warunków złączenia.

Oto kolejny przykład, tym razem przedstawiający relacje między pracownikami a menedżerami:

SELECT    *FROM    people AS employeeJOIN people AS manager    ON employee.manager_id = manager.id;



Warunki łączenia

Podczas łączenia tabel warunek łączenia określa, w jaki sposób wiersze będą dopasowywane do siebie w celu utworzenia wyników złożonych. Podstawowym założeniem jest zdefiniowanie kolumn w każdej tabeli, które muszą być zgodne, aby łączenie miało miejsce w tym wierszu.


ON klauzula

Najbardziej standardowym sposobem definiowania warunków łączenia tabel jest ON klauzula. ON klauzula używa znaku równości, aby określić dokładne kolumny z każdej tabeli, które będą porównywane w celu określenia, kiedy może wystąpić łączenie. PostgreSQL używa dostarczonych kolumn do łączenia wierszy z każdej tabeli.

ON klauzula jest najbardziej szczegółowa, ale także najbardziej elastyczna z dostępnych warunków złączenia. Pozwala to na precyzję niezależnie od tego, jak ustandaryzowane są nazwy kolumn w każdej łączonej tabeli.

Podstawowa składnia ON klauzula wygląda tak:

SELECT    *FROM    table1JOIN    table2ON    table1.id = table2.ident;

Tutaj wiersze z table1 i table2 zostanie dołączony za każdym razem, gdy id kolumna z table1 pasuje do ident kolumna z table2 . Ponieważ używane jest sprzężenie wewnętrzne, wyniki pokażą tylko te wiersze, które zostały połączone. Ponieważ zapytanie używa symbolu wieloznacznego * znak, zostaną wyświetlone wszystkie kolumny z obu tabel.

Oznacza to, że zarówno id kolumna z table1 i ident kolumna z table2 zostaną wyświetlone, nawet jeśli mają taką samą dokładną wartość z racji spełnienia warunku złączenia. Możesz uniknąć tego powielania, wywołując dokładnie te kolumny, które chcesz wyświetlić w SELECT lista kolumn.



USING klauzula

USING klauzula jest skrótem do określania warunków ON klauzula, której można użyć, gdy porównywane kolumny mają taką samą nazwę w obu tabelach. USING klauzula pobiera listę, ujętą w nawiasy, wspólnych nazw kolumn, które należy porównać.

Ogólna składnia USING klauzula używa tego formatu:

SELECT    *FROM    table1JOIN    table2USING    (id, state);

To połączenie łączy table1 z table2 gdy dwie kolumny współdzielone przez obie tabele (id i state ) każdy ma pasujące wartości.

To samo połączenie może być wyrażone bardziej szczegółowo przy użyciu ON tak:

SELECT    *FROM    table1JOIN    table2ON    table1.id = table2.id AND table1.state = table2.state;

Chociaż oba powyższe sprzężenia spowodowałyby skonstruowanie tych samych wierszy z tymi samymi danymi, byłyby wyświetlane nieco inaczej. Gdy ON klauzula zawiera wszystkie kolumny z obu tabel, USING klauzula pomija zduplikowane kolumny. Więc zamiast dwóch oddzielnych id kolumny i dwa oddzielne state kolumny (po jednej dla każdej tabeli), wyniki będą zawierały tylko jedną z każdej ze współdzielonych kolumn, a po niej wszystkie inne kolumny dostarczone przez table1 i table2 .



NATURAL klauzula

NATURAL klauzula jest kolejnym skrótem, który może jeszcze bardziej zmniejszyć szczegółowość USING klauzula. NATURAL dołącz nie określa żadnego kolumny do dopasowania. Zamiast tego PostgreSQL automatycznie połączy tabele na podstawie wszystkich kolumn, które mają pasujące kolumny w każdej bazie danych.

Ogólna składnia NATURAL klauzula join wygląda tak:

SELECT    *FROM    table1NATURAL JOIN    table2;

Zakładając, że table1 i table2 obie mają kolumny o nazwie id , state i company , powyższe zapytanie byłoby równoważne z tym zapytaniem przy użyciu ON klauzula:

SELECT    *FROM    table1JOIN    table2ON    table1.id = table2.id AND table1.state = table2.state AND table1.company = table2.company;

A to zapytanie przy użyciu USING klauzula:

SELECT    *FROM    table1JOIN    table2USING    (id, state, company);

Podobnie jak USING klauzula NATURAL klauzula wyłącza zduplikowane kolumny, więc w wynikach będzie tylko jedna instancja każdej z połączonych kolumn.

Podczas gdy NATURAL klauzula może zmniejszyć szczegółowość zapytań, należy zachować ostrożność podczas jej używania. Ponieważ kolumny używane do łączenia tabel są obliczane automatycznie, jeśli kolumny w tabelach składowych ulegną zmianie, wyniki mogą się znacznie różnić ze względu na nowe warunki łączenia.




Warunki łączenia i WHERE klauzula

Warunki łączenia mają wiele cech wspólnych z porównaniami używanymi do filtrowania wierszy danych za pomocą WHERE klauzule. Obie konstrukcje definiują wyrażenia, których wartością musi być prawda, aby wiersz był brany pod uwagę. Z tego powodu nie zawsze jest intuicyjne, jaka jest różnica między dołączaniem dodatkowych porównań w WHERE konstruować a nie definiować ich w samej klauzuli join.

Aby zrozumieć różnice, które wynikną, musimy przyjrzeć się kolejności, w jakiej PostgreSQL przetwarza różne części zapytania. W takim przypadku predykaty w warunku sprzężenia są najpierw przetwarzane w celu skonstruowania wirtualnej tabeli sprzężonej w pamięci. Po tym etapie wyrażenia w WHERE klauzule są oceniane w celu filtrowania wynikowych wierszy.

Jako przykład załóżmy, że mamy dwie tabele o nazwie customer i order że musimy się połączyć. Chcemy połączyć te dwie tabele, dopasowując customer.id kolumna z order.customer_id kolumna. Dodatkowo interesują nas wiersze w order tabela, która ma product_id z 12345.

Biorąc pod uwagę powyższe wymagania mamy dwa warunki, na których nam zależy. Sposób, w jaki wyrażamy te warunki, będzie jednak decydował o otrzymanych wynikach.

Najpierw użyjmy obu jako warunków łączenia dla LEFT JOIN :

SELECT    customer.id AS customer_id,    customer.name,    order.id AS order_id,    order.product_idFROM    customerLEFT JOIN    orderON    customer.id = order.customer_id AND order.product_id = 12345;

Wyniki mogą potencjalnie wyglądać mniej więcej tak:

 customer_id |   name   | order_id | product_id ------------+----------+----------+------------        4380 | Acme Co  |      480 |      12345        4380 | Acme Co  |      182 |      12345         320 | Other Co |      680 |      12345        4380 | Acme Co  |          |         320 | Other Co |          |          20 | Early Co |          |        8033 | Big Co   |          |(7 rows)

PostgreSQL osiągnął ten wynik, wykonując następujące operacje:

  1. Połącz dowolne wiersze w customer tabela z order tabela gdzie:
    • customer.id pasuje do order.customer_id .
    • order.product_id pasuje do 12345
  2. Ponieważ używamy lewego sprzężenia, uwzględnij wszystkie niedopasowane wiersze z lewej tabeli (customer ), dopełniając kolumny z prawej tabeli (order ) z NULL wartości.
  3. Wyświetl tylko kolumny wymienione w SELECT specyfikacja kolumny.

W rezultacie wszystkie nasze połączone rzędy spełniają oba warunki, których szukamy. Jednak lewe złączenie powoduje, że PostgreSQL uwzględnia również wszystkie wiersze z pierwszej tabeli, które nie spełniły warunku złączenia. Powoduje to powstanie „pozostawionych” wierszy, które wydają się nie odpowiadać widocznej intencji zapytania.

Jeśli przeniesiemy drugie zapytanie (order.product_id =12345) do WHERE klauzuli, zamiast uwzględniać ją jako warunek złączenia, otrzymujemy różne wyniki:

SELECT    customer.id AS customer_id,    customer.name,    order.id AS order_id,    order.product_idFROM    customerLEFT JOIN    orderON    customer.id = order.customer_idWHERE    order.product_id = 12345;

Tym razem wyświetlane są tylko trzy wiersze:

 customer_id |   name   | order_id | product_id ------------+----------+----------+------------        4380 | Acme Co  |      480 |      12345        4380 | Acme Co  |      182 |      12345         320 | Other Co |      680 |      12345(3 rows)

Powodem tych różnic jest kolejność wykonywania porównań. Tym razem PostgreSQL przetwarza zapytanie w ten sposób:

  1. Połącz dowolne wiersze w customer tabela z order tabela, w której customer.id pasuje do order.customer_id .
  2. Ponieważ używamy lewego sprzężenia, uwzględnij wszystkie niedopasowane wiersze z lewej tabeli (customer ), dopełniając kolumny z prawej tabeli (order ) z NULL wartości.
  3. Oceń WHERE klauzula usuwająca wszystkie wiersze, które nie mają 12345 jako wartości dla order.product_id kolumna.
  4. Wyświetl tylko kolumny wymienione w SELECT specyfikacja kolumny.

Tym razem, mimo że używamy lewego sprzężenia, WHERE klauzula obcina wyniki przez odfiltrowanie wszystkich wierszy bez poprawnego product_id . Ponieważ każdy niedopasowany wiersz miałby product_id ustaw na NULL , usuwa wszystkie niedopasowane wiersze, które zostały wypełnione przez lewe sprzężenie. Usuwa również wszystkie wiersze, które zostały dopasowane przez warunek złączenia, które nie przeszły tej drugiej rundy kontroli.

Zrozumienie podstawowego procesu używanego przez PostgreSQL do wykonywania zapytań może pomóc w uniknięciu niektórych łatwych do wykonania, ale trudnych do debugowania błędów podczas pracy z danymi.



Wniosek

W tym przewodniku omówiliśmy, w jaki sposób sprzężenia umożliwiają relacyjnym bazom danych łączenie danych z różnych tabel w celu uzyskania bardziej wartościowych odpowiedzi. Rozmawialiśmy o różnych sprzężeniach obsługiwanych przez PostgreSQL, sposobie, w jaki każdy typ zbiera swoje wyniki, oraz o tym, czego można się spodziewać podczas korzystania z określonych rodzajów sprzężeń. Następnie omówiliśmy różne sposoby definiowania warunków złączenia i przyjrzeliśmy się wzajemnemu oddziaływaniu złączeń i WHERE klauzula może prowadzić do niespodzianek.

Sprzężenia są istotną częścią tego, co sprawia, że ​​relacyjne bazy danych są wystarczająco wydajne i elastyczne, aby obsłużyć tak wiele różnych typów zapytań. Organizowanie danych przy użyciu granic logicznych, a jednocześnie możliwość ponownego łączenia danych w nowatorski sposób w poszczególnych przypadkach, zapewnia relacyjnym bazom danych, takim jak PostgreSQL, niesamowitą wszechstronność. Nauczenie się, jak wykonać to łączenie między tabelami, pozwoli Ci tworzyć bardziej złożone zapytania i polegać na bazie danych, aby tworzyć pełne obrazy Twoich danych.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. uWSGI, Flask, sqlalchemy i postgres:błąd SSL:odszyfrowanie nie powiodło się lub zły rekord mac

  2. Zapytanie PostgreSQL za pomocą Npgsql i Entity Framework przy użyciu nieakcentu

  3. Powrót z funkcji z parametrem OUT

  4. Nie można połączyć PostgreSQL ze zdalną bazą danych za pomocą pgAdmin

  5. PostgreSQL 8.4 przyznaje uprawnienia DML do wszystkich tabel do roli