{"id":545,"date":"2023-10-20T11:05:53","date_gmt":"2023-10-20T09:05:53","guid":{"rendered":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/?page_id=545"},"modified":"2025-07-26T15:51:42","modified_gmt":"2025-07-26T13:51:42","slug":"1-10-consultes-avancades-consultes-multitaula","status":"publish","type":"page","link":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/1-10-consultes-avancades-consultes-multitaula\/","title":{"rendered":"1.10. Consultes avan\u00e7ades: consultes multitaula"},"content":{"rendered":"<p>Per aprofitar al m\u00e0xim el model relacional i generar nou coneixement de les dades existents resulta essencial combinar informaci\u00f3 de diverses taules. Mitjan\u00e7ant un atribut que dues taules posseeixin en com\u00fa, aquesta operaci\u00f3 resulta extremadament senzilla amb SQL. Mentre efectuem una consulta amb l\u2019ordre <code>SELECT<\/code>, hem d\u2019emprar la cl\u00e0usula <code>JOIN<\/code> especificant l\u2019atribut compartit per ambdues taules. Quan es referencien atributs de dues o m\u00e9s taules en la mateixa consulta, cal utilitzar la sintaxi <code>nom_taula.nom_atribut<\/code> per especificar clarament l\u2019origen de cada atribut. \u00c9s possible afegir-hi condicions sobre altres atributs de les taules amb la cl\u00e0usula <code>WHERE<\/code>.<\/p>\n<p>Donades dues taules que denominarem <strong>taula1 <\/strong>i <strong>taula2<\/strong>, que posseeixen un atribut comparable (<strong>taula1.x<\/strong> i<strong> taula2.y<\/strong>), la sintaxi de l\u2019ordre <strong>JOIN<\/strong> per obtenir tant els valors en com\u00fa com els valors presents exclusivament en la primera o en la segona taula, respectivament, \u00e9s la seg\u00fcent:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">SELECT taula1.x,taula2.y\r\nFROM taula1 JOIN taula2\r\nON taula1.x=taula2.y\r\nWHERE condicions;\r\n----------------------------------------\r\nSELECT taula1.x,taula2.y\r\nFROM taula1 LEFT JOIN taula2\r\nON taula1.x=taula2.y\r\nWHERE condicions;\r\n----------------------------------------\r\nSELECT taula1.x,taula2.y\r\nFROM taula1 RIGHT JOIN taula2\r\nON taula1.x=taula2.y\r\nWHERE condicions;<\/pre>\n<div class=\"featured featured-blue\"><p>Per treballar amb m\u00e9s de dues taules, podem generalitzar la mateixa sintaxi (per exemple, taula1 JOIN (taula2,3,4)).<\/p>\n<\/div>\n<p>Abans de procedir a executar consultes sobre les taules de la base de dades, proposem posar a prova el funcionament de la cl\u00e0usula <code>JOIN<\/code> sobre un exemple m\u00e9s simple.<\/p>\n<p>Generarem dues taules que denominarem <strong>taula1 <\/strong>i <strong>taula2<\/strong>, amb un \u00fanic atribut. Posteriorment, poblarem ambdues taules amb una s\u00e8rie de valors tals que resultar\u00e0 molt senzill mostrar el conjunt complet de combinacions a l\u2019hora de comparar les dues taules.<\/p>\n<p>Primer procedim a crear les dues taules:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">mysql&gt; CREATE TABLE taula1\r\n    -&gt; (x VARCHAR(10));\r\n\r\nQuery OK, 0 rows affected (0.5 sec)\r\n\r\nmysql&gt; CREATE TABLE taula2\r\n     -&gt; (y VARCHAR(10));\r\n\r\nQuery OK, 0 rows affected (0.5 sec)<\/pre>\n<div class=\"featured featured-blue\"><p>Us animem a reproduir al vostre ordinador les ordres de SQL presentades en aquest apartat.<\/p>\n<\/div>\n<p>Ara crearem dos fitxers de text senzills amb tres valors cadascun: (1,2,3) i (3,4,5). D\u2019aquesta manera, podrem estudiar detalladament la classe de consulta de MySQL que necessitem per recuperar els valors comuns entre ambdues taules (3) o, alternativament, els valors que \u00fanicament apareixen a la primera (1 i 2) o a la segona taula (4 i 5).<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">1\r\n2\r\n3\r\n\r\n---------------------------------------------\r\n\r\n3\r\n4\r\n5<\/pre>\n<p>Finalment, poblem les dues taules utilitzant ambd\u00f3s fitxers:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">mysql&gt; LOAD DATA LOCAL INFILE 'dades1.txt' INTO TABLE taula1;\r\n\r\nQuery OK, 3 rows affected (0.67 sec)\r\nRecords: 3  Deleted: 0  Skipped: 0  Warnings: 0\r\n\r\nmysql&gt; LOAD DATA LOCAL INFILE 'dades2.txt' INTO TABLE taula2;\r\n\r\nQuery OK, 3 rows affected (0.43 sec)\r\nRecords: 3  Deleted: 0  Skipped: 0  Warnings: 0<\/pre>\n<p>Ja estem en disposici\u00f3 d\u2019aprofundir en el funcionament de les consultes que inclouen la cl\u00e0usula <code>JOIN<\/code>. Si no hi afegim cap opci\u00f3, aquesta ordre genera totes les parelles possibles el primer element de les quals pertany a la primera taula i el segon element pertany a la segona:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">mysql&gt; SELECT taula1.x,taula2.y\r\n    -&gt; FROM taula1 JOIN taula2;\r\n\r\n+-----+-----+\r\n| x   | y   |\r\n+-----+-----+\r\n| 1   | 3   |\r\n| 2   | 3   |\r\n| 3   | 3   |\r\n| 1   | 4   |\r\n| 2   | 4   |\r\n| 3   | 4   |\r\n| 1   | 5   |\r\n| 2   | 5   |\r\n| 3   | 5   |\r\n+-----+-----+\r\n9 rows in set (0.00 sec)<\/pre>\n<p>El nostre primer objectiu en una comparaci\u00f3 \u00e9s localitzar els elements comuns. Per tal de fer-ho n\u2019hi ha prou amb incorporar la cl\u00e0usula <strong>ON<\/strong> a la consulta i especificar l\u2019atribut compartit per les dues taules. Aix\u00f2 filtrar\u00e0 aquelles parelles del resultat anterior que no compleixin aquesta propietat, i es demostrar\u00e0 all\u00f2 que busquem:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">mysql&gt; SELECT taula1.x,taula2.y\r\n    -&gt; FROM taula1 JOIN taula2\r\n    -&gt; ON taula1.x=taula2.y;\r\n\r\n+-----+-----+\r\n| x   | y   |\r\n+-----+-----+\r\n| 3   | 3   |\r\n+-----+-----+\r\n1 row in set (0.00 sec)<\/pre>\n<p>En determinats casos, en lloc de la llista dels valors comuns, estarem interessats tamb\u00e9 en aquells valors d\u2019una o altra taula que no pertanyen a l\u2019altra. Per aix\u00f2 hem de modificar el comportament de l\u2019ordre <code>JOIN<\/code> amb les cl\u00e0usules <code>LEFT<\/code> o <code>RIGHT<\/code>. Si realitzem una uni\u00f3 per la part esquerra, recuperarem un llistat dels registres de la primera taula juntament amb el seu registre equivalent a la segona. En el cas que aquest valor an\u00e0leg no exist\u00eds, MySQL ho indicar\u00e0 amb el valor <code>NULL<\/code>. Si, per contra, realitzem la uni\u00f3 per la dreta, obtindrem un llistat dels valors de la segona taula sota les mateixes condicions.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">mysql&gt; SELECT taula1.x,taula2.y\r\n    -&gt; FROM taula1 LEFT JOIN taula2\r\n    -&gt; ON taula1.x=taula2.y;\r\n\r\n+-----+------+\r\n| x   | y    |\r\n+-----+------+\r\n| 3   | 3    |\r\n| 1   | NULL |\r\n| 2   | NULL |\r\n+-----+------+\r\n3 rows in set (0.00 sec)\r\n\r\nmysql&gt; SELECT taula1.x,taula2.y\r\n    -&gt; FROM taula1 RIGHT JOIN taula2\r\n    -&gt; ON taula1.x=taula2.y;\r\n\r\n+------+-----+\r\n| x    | y   |\r\n+------+-----+\r\n| 3    | 3   |\r\n| NULL | 4   |\r\n| NULL | 5   |\r\n+------+-----+\r\n3 rows in set (0.00 sec)<\/pre>\n<p>Per acabar de refinar el resultat, hem de mantenir exclusivament els valors que nom\u00e9s estan en una taula. Per aconseguir-ho, podem afegir al final de la consulta una condici\u00f3 <code>WHERE<\/code> que exigeixi que el valor no estigui present a l\u2019altra taula. La cl\u00e0usula IS realitza l\u2019avaluaci\u00f3 de l\u2019expressi\u00f3 que es troba a continuaci\u00f3, per acabar responent amb un valor boole\u00e0 (cert o fals).<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">mysql&gt; SELECT taula1.x,taula2.y\r\n    -&gt; FROM taula1 LEFT JOIN taula2\r\n    -&gt; ON taula1.x=taula2.y\r\n    -&gt; WHERE taula2.y IS NULL;\r\n\r\n+-----+------+\r\n| x   | y    |\r\n+-----+------+\r\n| 1   | NULL |\r\n| 2   | NULL |\r\n+-----+------+\r\n2 rows in set (0.00 sec)\r\n\r\nmysql&gt; SELECT taula1.x,taula2.y\r\n    -&gt; FROM taula1 RIGHT JOIN taula2\r\n    -&gt; ON taula1.x=taula2.y\r\n    -&gt; WHERE taula1.x IS NULL;\r\n\r\n+------+-----+\r\n| x    | y   |\r\n+------+-----+\r\n| NULL | 4   |\r\n| NULL | 5   |\r\n+------+-----+\r\n2 rows in set (0.00 sec)<\/pre>\n<p>Ara ja estem en condicions de realitzar consultes sobre dues o m\u00e9s taules del nostre cat\u00e0leg de gens. Per exemple, podem preguntar per aquells gens humans per als quals s\u2019ha documentat una anotaci\u00f3 funcional de car\u00e0cter experimental:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">mysql&gt; SELECT gens.nom,gens.especie,\r\n    -&gt; anotacions.funcio,anotacions.origen\r\n    -&gt; FROM gens JOIN anotacions\r\n    -&gt; ON gens.nom=anotacions.nom\r\n    -&gt; WHERE anotacions.origen='experimental'\r\n    -&gt; AND gens.especie='H. sapiens';\r\n\r\n+-------+------------+------------+--------------+\r\n| nom   |   especie  |   funcio   |    origen    |\r\n+-------+------------+------------+--------------+\r\n| HNF1A | H. sapiens | GO:0003700 | Experimental |\r\n| MYC   | H. sapiens | GO:0003700 | Experimental |\r\n+-------+------------+------------+--------------+\r\n2 rows in set (0.00 sec)<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Per aprofitar al m\u00e0xim el model relacional i generar nou coneixement de les dades existents resulta essencial combinar informaci\u00f3 de diverses taules. Mitjan\u00e7ant un atribut que dues taules posseeixin en com\u00fa, aquesta operaci\u00f3 resulta extremadament senzilla amb SQL. Mentre efectuem una consulta amb l\u2019ordre SELECT, hem d\u2019emprar la cl\u00e0usula JOIN especificant l\u2019atribut compartit per ambdues [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"acf":[],"_links":{"self":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/wp-json\/wp\/v2\/pages\/545"}],"collection":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/wp-json\/wp\/v2\/comments?post=545"}],"version-history":[{"count":17,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/wp-json\/wp\/v2\/pages\/545\/revisions"}],"predecessor-version":[{"id":1038,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/wp-json\/wp\/v2\/pages\/545\/revisions\/1038"}],"wp:attachment":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/wp-json\/wp\/v2\/media?parent=545"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}