<div class="page"> <div class="cover text-center"> <img class="mx-auto" src=/itb/images/logo_mislata.png alt="logo"> # Consultes amb múltiples taules <div class="text-end fit-content ms-auto my-3 mt-auto pt-3"> <p><strong>Autor:</strong> Joan Puigcerver Ibáñez</p> <p><strong>Correu electrònic:</strong> j.puigcerveribanez@edu.gva.es</p> <p><strong>Curs:</strong> 2023/2024</p> </div> <div> <p class="fw-bold mb-0">Llicència: BY-NC-SA</p> <p class="d-none d-md-block">(Reconeixement - No Comercial - Compartir Igual)</p> <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.ca" target="_blank"> <img class="mx-auto" src="/itb/images/license.png" alt="Licence"/> </a> </div><!--license--> </div><!--cover--> </div><!--page--> {:toc} ## Introducció Fins ara hem realitzat consultes `SELECT` a partir una única taula (`FROM`). No obstant això, les bases de dades relacionals estan pensades per relacionar les dades de múltiples taules, navegant les claus foranes i combinant la informació per extraure dades que complixen condicions més complexes. Hi ha diferents maneres de combinar múltiples taules, però la més elegant és mitjançant la clàusula `JOIN`. ::: docs Documentació oficial sobre `JOIN`: - MariaDB: https://mariadb.com/kb/en/joins/ - MySQL 8.0: https://dev.mysql.com/doc/refman/8.0/en/join.html ::: ## Taules i dades d'exemple Tots els exemples es realitzaran amb les següents taules i dades: ```sql CREATE DATABASE tenda; USE tenda; CREATE TABLE categoria ( id_categoria INT PRIMARY KEY AUTO_INCREMENT, nom VARCHAR(50) NOT NULL ); CREATE TABLE producte ( id_producte INT PRIMARY KEY AUTO_INCREMENT, id_categoria INT, nom VARCHAR(50) NOT NULL, preu DECIMAL(5,2) NOT NULL, FOREIGN KEY (id_categoria) REFERENCES categoria (id_categoria) ); INSERT INTO categoria (id_categoria, nom) VALUES (1, "Forn"), (2, "Beguda"), (3, "Higiene"), (4, "Fruta"); INSERT INTO producte (id_producte, id_categoria, nom, preu) VALUES (1, 1, "Barra de pà", 0.7), (2, 1, "Pastís de xocolate", 5.3), (3, 2, "Botella d'aigua 50cL", 0.8), (4, NULL, "Piles AA", 1.5), (5, 4, "Pera", 0.3), (6, 4, "Plàtan", 0.5); ``` <div class="d-flex justify-content-evenly flex-wrap"> <table> <caption>Figura 2.1: Taula Catgoria amb les seues dades</caption> <thead> <tr> <th style="text-align:center" colspan="2">Taula Categoria</th> </tr> <tr> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> </tr> </thead> <tbody> <tr class="orange1"> <td style="text-align:center">1</td> <td style="text-align:center">Forn </td> </tr> <tr class="orange2"> <td style="text-align:center">2</td> <td style="text-align:center">Beguda </td> </tr> <tr class="orange3"> <td style="text-align:center">3</td> <td style="text-align:center">Higiene</td> </tr> <tr class="orange4"> <td style="text-align:center">4</td> <td style="text-align:center">Fruta </td> </tr> </tbody> </table> <table> <caption>Figura 2.2: Taula Producte amb les seues dades</caption> <thead> <tr> <th style="text-align:center" colspan="4">Taula Producte</th> </tr> <tr> <th style="text-align:center">ID Producte</th> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">Preu</th> </tr> </thead> <tbody> <tr class="blue1"> <td style="text-align:center">1</td> <td style="text-align:center">1</td> <td style="text-align:center">Barra de pà</td> <td style="text-align:center">0.70</td> </tr> <tr class="blue2"> <td style="text-align:center">2</td> <td style="text-align:center">1</td> <td style="text-align:center">Pastís de xocolate</td> <td style="text-align:center">5.30</td> </tr> <tr class="blue3"> <td style="text-align:center">3</td> <td style="text-align:center">2</td> <td style="text-align:center">Botella d'aigua 50cL</td> <td style="text-align:center">0.80</td> </tr> <tr class="blue4"> <td style="text-align:center">4</td> <td style="text-align:center">NULL</td> <td style="text-align:center">Piles AA</td> <td style="text-align:center">1.50</td> </tr> <tr class="blue5"> <td style="text-align:center">5</td> <td style="text-align:center">4</td> <td style="text-align:center">Pera</td> <td style="text-align:center">0.30</td> </tr> <tr class="blue6"> <td style="text-align:center">6</td> <td style="text-align:center">4</td> <td style="text-align:center">Plàtan</td> <td style="text-align:center">0.50</td> </tr> </tbody> </table> </div> ## Producte cartesià o `CROSS JOIN` Sempre que es desitge combinar múltiples taules, el SGBD realitzarà el __producte cartesià__ entre les taules, que després filtrarà per obtindre el resultat esperat. #3.1[Producte cartesià entre dos conjunts](/itb/DAM-BD/UD5/img/joins/cross_join.svg) El producte cartesià retorna una taula on cada element d'una taula estarà combinat amb cadascun dels elements de l'altra taula. ::: example <table id="figure-3.2" class="center"> <caption>Figura 3.2: Resultat del producte cartesià entre les taules Producte i Categoria</caption> <thead> <tr> <th style="text-align:center" colspan="2">Taula Categoria</th> <th style="text-align:center" colspan="4">Taula Producte</th> </tr> <tr> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">ID Producte</th> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">Preu</th> </tr> </thead> <tbody> <!-- 1 Forn --> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">Barra de pà</td> <td style="text-align:center" class="blue1">0.70</td> </tr> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue2">2</td> <td style="text-align:center" class="blue2">1</td> <td style="text-align:center" class="blue2">Pastís de xocolate</td> <td style="text-align:center" class="blue2">5.30</td> </tr> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue3">3</td> <td style="text-align:center" class="blue3">2</td> <td style="text-align:center" class="blue3">Botella d'aigua 50cL</td> <td style="text-align:center" class="blue3">0.80</td> </tr> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue4">4</td> <td style="text-align:center" class="blue4">NULL</td> <td style="text-align:center" class="blue4">Piles AA</td> <td style="text-align:center" class="blue4">1.50</td> </tr> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue5">5</td> <td style="text-align:center" class="blue5">4</td> <td style="text-align:center" class="blue5">Pera</td> <td style="text-align:center" class="blue5">0.30</td> </tr> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue6">6</td> <td style="text-align:center" class="blue6">4</td> <td style="text-align:center" class="blue6">Plàtan</td> <td style="text-align:center" class="blue6">0.50</td> <!-- 2 Beguda --> <tr> <td style="text-align:center" class="orange2">2</td> <td style="text-align:center" class="orange2">Beguda</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">Barra de pà</td> <td style="text-align:center" class="blue1">0.70</td> </tr> <tr> <td style="text-align:center" class="orange2">2</td> <td style="text-align:center" class="orange2">Beguda</td> <td style="text-align:center" class="blue2">2</td> <td style="text-align:center" class="blue2">1</td> <td style="text-align:center" class="blue2">Pastís de xocolate</td> <td style="text-align:center" class="blue2">5.30</td> </tr> <tr> <td style="text-align:center" class="orange2">2</td> <td style="text-align:center" class="orange2">Beguda</td> <td style="text-align:center" class="blue3">3</td> <td style="text-align:center" class="blue3">2</td> <td style="text-align:center" class="blue3">Botella d'aigua 50cL</td> <td style="text-align:center" class="blue3">0.80</td> </tr> <tr> <td style="text-align:center" class="orange2">2</td> <td style="text-align:center" class="orange2">Beguda</td> <td style="text-align:center" class="blue4">4</td> <td style="text-align:center" class="blue4">NULL</td> <td style="text-align:center" class="blue4">Piles AA</td> <td style="text-align:center" class="blue4">1.50</td> </tr> <tr> <td style="text-align:center" class="orange2">2</td> <td style="text-align:center" class="orange2">Beguda</td> <td style="text-align:center" class="blue5">5</td> <td style="text-align:center" class="blue5">4</td> <td style="text-align:center" class="blue5">Pera</td> <td style="text-align:center" class="blue5">0.30</td> </tr> <tr> <td style="text-align:center" class="orange2">2</td> <td style="text-align:center" class="orange2">Beguda</td> <td style="text-align:center" class="blue6">6</td> <td style="text-align:center" class="blue6">4</td> <td style="text-align:center" class="blue6">Plàtan</td> <td style="text-align:center" class="blue6">0.50</td> <!-- 3 Higiene --> <tr> <td style="text-align:center" class="orange3">3</td> <td style="text-align:center" class="orange3">Higiene</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">Barra de pà</td> <td style="text-align:center" class="blue1">0.70</td> </tr> <tr> <td style="text-align:center" class="orange3">3</td> <td style="text-align:center" class="orange3">Higiene</td> <td style="text-align:center" class="blue2">2</td> <td style="text-align:center" class="blue2">1</td> <td style="text-align:center" class="blue2">Pastís de xocolate</td> <td style="text-align:center" class="blue2">5.30</td> </tr> <tr> <td style="text-align:center" class="orange3">3</td> <td style="text-align:center" class="orange3">Higiene</td> <td style="text-align:center" class="blue3">3</td> <td style="text-align:center" class="blue3">2</td> <td style="text-align:center" class="blue3">Botella d'aigua 50cL</td> <td style="text-align:center" class="blue3">0.80</td> </tr> <tr> <td style="text-align:center" class="orange3">3</td> <td style="text-align:center" class="orange3">Higiene</td> <td style="text-align:center" class="blue4">4</td> <td style="text-align:center" class="blue4">NULL</td> <td style="text-align:center" class="blue4">Piles AA</td> <td style="text-align:center" class="blue4">1.50</td> </tr> <tr> <td style="text-align:center" class="orange3">3</td> <td style="text-align:center" class="orange3">Higiene</td> <td style="text-align:center" class="blue5">5</td> <td style="text-align:center" class="blue5">4</td> <td style="text-align:center" class="blue5">Pera</td> <td style="text-align:center" class="blue5">0.30</td> </tr> <tr> <td style="text-align:center" class="orange3">3</td> <td style="text-align:center" class="orange3">Higiene</td> <td style="text-align:center" class="blue6">6</td> <td style="text-align:center" class="blue6">4</td> <td style="text-align:center" class="blue6">Plàtan</td> <td style="text-align:center" class="blue6">0.50</td> <!-- 4 Fruta --> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">Barra de pà</td> <td style="text-align:center" class="blue1">0.70</td> </tr> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue2">2</td> <td style="text-align:center" class="blue2">1</td> <td style="text-align:center" class="blue2">Pastís de xocolate</td> <td style="text-align:center" class="blue2">5.30</td> </tr> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue3">3</td> <td style="text-align:center" class="blue3">2</td> <td style="text-align:center" class="blue3">Botella d'aigua 50cL</td> <td style="text-align:center" class="blue3">0.80</td> </tr> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue4">4</td> <td style="text-align:center" class="blue4">NULL</td> <td style="text-align:center" class="blue4">Piles AA</td> <td style="text-align:center" class="blue4">1.50</td> </tr> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue5">5</td> <td style="text-align:center" class="blue5">4</td> <td style="text-align:center" class="blue5">Pera</td> <td style="text-align:center" class="blue5">0.30</td> </tr> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue6">6</td> <td style="text-align:center" class="blue6">4</td> <td style="text-align:center" class="blue6">Plàtan</td> <td style="text-align:center" class="blue6">0.50</td> </tr> </tbody> </table> ::: El SGBD retornarà el producte cartesià entre dues taules si: - Realitzem un `JOIN` o `CROSS JOIN` sense cap condició. ::: example ```sql SELECT * FROM categoria CROSS JOIN producte; ``` ::: - Realitzem una consulta amb múltiples taules en la clàusula `FROM`. ::: example ```sql SELECT * FROM categoria, producte; ``` ::: ## Combinació interna o `INNER JOIN` El producte cartesià ens retorna totes les possibles combinacions entre diferents taules i molts dels resultats no estan relacionats entre sí. Per filtrar els resultats i retornar sols aquells registres que sí que estan relacionats entre si, cal utilitzar `INNER JOIN`, que permet especificar una condició per especificar com es relacionen els registres de les diferents taules. Normalment aquesta condició utilitza les claus foranes definides. #4.1[Intersecció entre dos conjunts](/itb/DAM-BD/UD5/img/joins/inner_join.svg) La clàusula `INNER JOIN` té la següent sintaxi: ```sql SELECT columns FROM table1 t1 INNER JOIN table2 t2 ON t1.attr = t2.attr ``` - `INNER JOIN`: Especifica la taula que es dessitja combinar. Es pot especificar un àlies. - `ON`: Especifica els atributs que formen la relació entre les dues taules. Especifica la condició de filtratge. ::: info Es poden definir àlies en les taules per poder referenciar les taules d'una manerà més fàcil i còmoda. ::: ::: example La intersecció entre les taules Categoria i Producte ens retorna els productes relacionats amb les categories als quals pertanyen. <table id="figure-4.2" class="center"> <caption>Figura 4.2: Resultat del <code>INNER JOIN</code> entre les taules Producte i Categoria</caption> <thead> <tr> <th style="text-align:center" colspan="2">Taula Categoria</th> <th style="text-align:center" colspan="4">Taula Producte</th> </tr> <tr> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">ID Producte</th> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">Preu</th> </tr> </thead> <tbody> <!-- 1 Forn --> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">Barra de pà</td> <td style="text-align:center" class="blue1">0.70</td> </tr> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue2">2</td> <td style="text-align:center" class="blue2">1</td> <td style="text-align:center" class="blue2">Pastís de xocolate</td> <td style="text-align:center" class="blue2">5.30</td> </tr> <!-- 2 Beguda --> <tr> <td style="text-align:center" class="orange2">2</td> <td style="text-align:center" class="orange2">Beguda</td> <td style="text-align:center" class="blue3">3</td> <td style="text-align:center" class="blue3">2</td> <td style="text-align:center" class="blue3">Botella d'aigua 50cL</td> <td style="text-align:center" class="blue3">0.80</td> </tr> <!-- 4 Fruta --> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue5">5</td> <td style="text-align:center" class="blue5">4</td> <td style="text-align:center" class="blue5">Pera</td> <td style="text-align:center" class="blue5">0.30</td> </tr> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue6">6</td> <td style="text-align:center" class="blue6">4</td> <td style="text-align:center" class="blue6">Plàtan</td> <td style="text-align:center" class="blue6">0.50</td> </tr> </tbody> </table> Aquest resultat es pot obtindre mitjançant la consulta: ```sql SELECT c.id_categoria, c.nom, p.id_producte, p.id_categoria, p.nom, p.preu FROM categoria c INNER JOIN producte p ON p.id_categoria = c.id_categoria; ``` S'ha especificat en la condició `ON` que relacione la taula Producte amb la taula Categoria mitjançant la clau forana `id_categoria`. ::: ## Combinació externa: `LEFT JOIN` La combinació externa `LEFT JOIN` retorna aquells registres que estan relacionats en les dues taules (`INNER JOIN`), però també retorna els valors de la primera taula que no estan relacionats amb elements de la segona taula. #5.1[LEFT JOIN entre dos conjunts](/itb/DAM-BD/UD5/img/joins/left_join.svg) La clàusula `LEFT JOIN` té una sintaxi equivalent a `INNER JOIN`: ```sql SELECT columns FROM table1 t1 LEFT JOIN table2 t2 ON t1.attr = t2.attr ``` ::: example El `LEFT JOIN` entre les taules Categoria i Producte ens retorna les categories relacionades amb els productes que tenen, però també aquelles categories que no tenen cap producte. <table id="figure-5.2" class="center"> <caption>Figura 5.2: Resultat del LEFT JOIN entre les taules Producte i Categoria</caption> <thead> <tr> <th style="text-align:center" colspan="2">Taula Categoria</th> <th style="text-align:center" colspan="4">Taula Producte</th> </tr> <tr> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">ID Producte</th> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">Preu</th> </tr> </thead> <tbody> <!-- 1 Forn --> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">Barra de pà</td> <td style="text-align:center" class="blue1">0.70</td> </tr> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue2">2</td> <td style="text-align:center" class="blue2">1</td> <td style="text-align:center" class="blue2">Pastís de xocolate</td> <td style="text-align:center" class="blue2">5.30</td> </tr> <!-- 2 Beguda --> <tr> <td style="text-align:center" class="orange2">2</td> <td style="text-align:center" class="orange2">Beguda</td> <td style="text-align:center" class="blue3">3</td> <td style="text-align:center" class="blue3">2</td> <td style="text-align:center" class="blue3">Botella d'aigua 50cL</td> <td style="text-align:center" class="blue3">0.80</td> </tr> <!-- 3 Higiene --> <tr> <td style="text-align:center" class="orange3">3</td> <td style="text-align:center" class="orange3">Higiene</td> <td style="text-align:center" class="">NULL</td> <td style="text-align:center" class="">NULL</td> <td style="text-align:center" class="">NULL</td> <td style="text-align:center" class="">NULL</td> </tr> <!-- 4 Fruta --> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue5">5</td> <td style="text-align:center" class="blue5">4</td> <td style="text-align:center" class="blue5">Pera</td> <td style="text-align:center" class="blue5">0.30</td> </tr> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue6">6</td> <td style="text-align:center" class="blue6">4</td> <td style="text-align:center" class="blue6">Plàtan</td> <td style="text-align:center" class="blue6">0.50</td> </tr> </tbody> </table> Aquest resultat es pot obtindre mitjançant la consulta: ```sql SELECT c.id_categoria, c.nom, p.id_producte, p.id_categoria, p.nom, p.preu FROM categoria c LEFT JOIN producte p ON p.id_categoria = c.id_categoria; ``` ::: ## Combinació externa: `RIGHT JOIN` La combinació externa `RIGHT JOIN` retorna aquells registres que estan relacionats en les dues taules (`INNER JOIN`), però també retorna els valors de la segona taula que no estan relacionats amb elements de la primera taula. És exactament el mateix que un `LEFT JOIN` però en el altre sentit. #6.1[RIGHT JOIN entre dos conjunts](/itb/DAM-BD/UD5/img/joins/right_join.svg) La clàusula `RIGHT JOIN` té una sintaxi equivalent a `INNER JOIN`: ```sql SELECT columns FROM table1 t1 RIGHT JOIN table2 t2 ON t1.attr = t2.attr ``` ::: example El `RIGHT JOIN` entre les taules Categoria i Producte ens retorna les categories relacionades amb els productes que tenen, però també aquells productes que no tenen cap categoria. <table id="figure-6.2" class="center"> <caption>Figura 6.2: Resultat del RIGHT JOIN entre les taules Producte i Categoria</caption> <thead> <tr> <th style="text-align:center" colspan="2">Taula Categoria</th> <th style="text-align:center" colspan="4">Taula Producte</th> </tr> <tr> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">ID Producte</th> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">Preu</th> </tr> </thead> <tbody> <!-- 1 Forn --> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">Barra de pà</td> <td style="text-align:center" class="blue1">0.70</td> </tr> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue2">2</td> <td style="text-align:center" class="blue2">1</td> <td style="text-align:center" class="blue2">Pastís de xocolate</td> <td style="text-align:center" class="blue2">5.30</td> </tr> <!-- 2 Beguda --> <tr> <td style="text-align:center" class="orange2">2</td> <td style="text-align:center" class="orange2">Beguda</td> <td style="text-align:center" class="blue3">3</td> <td style="text-align:center" class="blue3">2</td> <td style="text-align:center" class="blue3">Botella d'aigua 50cL</td> <td style="text-align:center" class="blue3">0.80</td> </tr> <!-- Sense categoria --> <tr> <td style="text-align:center" class="">NULL</td> <td style="text-align:center" class="">NULL</td> <td style="text-align:center" class="blue4">4</td> <td style="text-align:center" class="blue4">NULL</td> <td style="text-align:center" class="blue4">Piles AA</td> <td style="text-align:center" class="blue4">1.50</td> </tr> <!-- 4 Fruta --> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue5">5</td> <td style="text-align:center" class="blue5">4</td> <td style="text-align:center" class="blue5">Pera</td> <td style="text-align:center" class="blue5">0.30</td> </tr> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue6">6</td> <td style="text-align:center" class="blue6">4</td> <td style="text-align:center" class="blue6">Plàtan</td> <td style="text-align:center" class="blue6">0.50</td> </tr> </tbody> </table> Aquest resultat es pot obtindre mitjançant la consulta: ```sql SELECT c.id_categoria, c.nom, p.id_producte, p.id_categoria, p.nom, p.preu FROM categoria c RIGHT JOIN producte p ON p.id_categoria = c.id_categoria; ``` ::: ## Combinació externa: `FULL JOIN` La combinació externa `FULL JOIN` retorna aquells registres que estan relacionats en les dues taules (`INNER JOIN`), però també retorna els valors de de les dues taules que no estan relacionats amb elements de l'altra taula (`LEFT JOIN` i `RIGHT JOIN`). #7.1[FULL JOIN entre dos conjunts](/itb/DAM-BD/UD5/img/joins/full_join.svg) No existeix la clàusula `FULL JOIN`, però podem obtindre el resultat mitjançant la clàusula `UNION`, que retorna els registres presents en dues consultes: ```sql SELECT columns FROM table1 t1 LEFT JOIN table2 t2 ON t1.attr = t2.attr UNION SELECT columns FROM table1 t1 RIGHT JOIN table2 t2 ON t1.attr = t2.attr ``` ::: example El `FULL JOIN` entre les taules Categoria i Producte ens retorna les categories relacionades amb els productes que tenen, però també aquells productes que no tenen cap categoria i les categories que no tenen cap producte. <table id="figure-5.2" class="center"> <caption>Figura 5.2: Resultat del LEFT JOIN entre les taules Producte i Categoria</caption> <thead> <tr> <th style="text-align:center" colspan="2">Taula Categoria</th> <th style="text-align:center" colspan="4">Taula Producte</th> </tr> <tr> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">ID Producte</th> <th style="text-align:center">ID Categoria</th> <th style="text-align:center">Nom</th> <th style="text-align:center">Preu</th> </tr> </thead> <tbody> <!-- 1 Forn --> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">1</td> <td style="text-align:center" class="blue1">Barra de pà</td> <td style="text-align:center" class="blue1">0.70</td> </tr> <tr> <td style="text-align:center" class="orange1">1</td> <td style="text-align:center" class="orange1">Forn</td> <td style="text-align:center" class="blue2">2</td> <td style="text-align:center" class="blue2">1</td> <td style="text-align:center" class="blue2">Pastís de xocolate</td> <td style="text-align:center" class="blue2">5.30</td> </tr> <!-- 2 Beguda --> <tr> <td style="text-align:center" class="orange2">2</td> <td style="text-align:center" class="orange2">Beguda</td> <td style="text-align:center" class="blue3">3</td> <td style="text-align:center" class="blue3">2</td> <td style="text-align:center" class="blue3">Botella d'aigua 50cL</td> <td style="text-align:center" class="blue3">0.80</td> </tr> <!-- 3 Higiene --> <tr> <td style="text-align:center" class="orange3">3</td> <td style="text-align:center" class="orange3">Higiene</td> <td style="text-align:center" class="">NULL</td> <td style="text-align:center" class="">NULL</td> <td style="text-align:center" class="">NULL</td> <td style="text-align:center" class="">NULL</td> </tr> <!-- Sense categoria --> <tr> <td style="text-align:center" class="">NULL</td> <td style="text-align:center" class="">NULL</td> <td style="text-align:center" class="blue4">4</td> <td style="text-align:center" class="blue4">NULL</td> <td style="text-align:center" class="blue4">Piles AA</td> <td style="text-align:center" class="blue4">1.50</td> </tr> <!-- 4 Fruta --> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue5">5</td> <td style="text-align:center" class="blue5">4</td> <td style="text-align:center" class="blue5">Pera</td> <td style="text-align:center" class="blue5">0.30</td> </tr> <tr> <td style="text-align:center" class="orange4">4</td> <td style="text-align:center" class="orange4">Fruta</td> <td style="text-align:center" class="blue6">6</td> <td style="text-align:center" class="blue6">4</td> <td style="text-align:center" class="blue6">Plàtan</td> <td style="text-align:center" class="blue6">0.50</td> </tr> </tbody> </table> Aquest resultat es pot obtindre mitjançant la consulta: ```sql SELECT c.id_categoria, c.nom, p.id_producte, p.id_categoria, p.nom, p.preu FROM categoria c LEFT JOIN producte p ON p.id_categoria = c.id_categoria UNION SELECT c.id_categoria, c.nom, p.id_producte, p.id_categoria, p.nom, p.preu FROM categoria c RIGHT JOIN producte p ON p.id_categoria = c.id_categoria; ``` ::: ## Bibliografia - https://es.wikipedia.org/wiki/Sentencia_JOIN_en_SQL - https://stackoverflow.com/questions/4796872/how-can-i-do-a-full-outer-join-in-mysql