<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5839769424182418749</id><updated>2011-07-07T19:42:51.847-07:00</updated><category term='mysql full join query union left join multiple tables'/><title type='text'>A revolution from my mind</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://disemq21.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5839769424182418749/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://disemq21.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>edward</name><uri>http://www.blogger.com/profile/14900140765215146649</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>2</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5839769424182418749.post-4644739718305245331</id><published>2009-08-13T15:10:00.000-07:00</published><updated>2009-08-13T15:20:49.126-07:00</updated><title type='text'>orto-grafía</title><content type='html'>Será que el oráculo le recortó el presupuesto al sol y a este no le alcanzó para implementar el corrector?&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_6iqVL5F2Umo/SoSQAB7FYZI/AAAAAAAAAAM/-TYW85mczcI/s1600-h/elejir.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 286px;" src="http://4.bp.blogspot.com/_6iqVL5F2Umo/SoSQAB7FYZI/AAAAAAAAAAM/-TYW85mczcI/s320/elejir.jpg" alt="" id="BLOGGER_PHOTO_ID_5369574985923125650" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5839769424182418749-4644739718305245331?l=disemq21.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://disemq21.blogspot.com/feeds/4644739718305245331/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5839769424182418749&amp;postID=4644739718305245331' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5839769424182418749/posts/default/4644739718305245331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5839769424182418749/posts/default/4644739718305245331'/><link rel='alternate' type='text/html' href='http://disemq21.blogspot.com/2009/08/orto-grafia.html' title='orto-grafía'/><author><name>edward</name><uri>http://www.blogger.com/profile/14900140765215146649</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_6iqVL5F2Umo/SoSQAB7FYZI/AAAAAAAAAAM/-TYW85mczcI/s72-c/elejir.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5839769424182418749.post-8755167421375019291</id><published>2009-08-07T15:05:00.000-07:00</published><updated>2009-08-07T15:25:15.655-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql full join query union left join multiple tables'/><title type='text'>Another MySQL Full Join</title><content type='html'>&lt;p&gt;Hace algún tiempo atrás, tuve la necesidad de hacer un listado del cual necesitaba mostrar todos los nulos de ambas tablas en relación a un campo en particular, entonces dije "bien, Full Join, ahora te toca."&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Pero no fue tan fácil. Viendo la documentación de mi MySQL, no encontré nada con respecto a Full Joins. Googleando un poco me dí cuenta de que MySQL no soportaba Full Joins.. Así, de una manera nada elegante, pude llegar a una solución (para ese listado en particular).&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Nuevamente buscando en google (a ver si me topaba algo más elegante) encontré varios posts al respecto. No era el único desesperado buscando &lt;a href="http://www.google.com.py/search?q=mysql+%22full+join%22&amp;amp;btnG=Buscar"&gt;Full Joins en Mysql&lt;/a&gt;.. Pero los que encontré, apuntaban a la misma solución que había armado primeramente (Incluso en el sitio de mysql tech resources apuntan esta misma solución):&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;a href="http://dev.mysql.com/tech-resources/articles/mysql-db-design-ch5.html"&gt;&lt;br /&gt;http://dev.mysql.com/tech-resources/articles/mysql-db-design-ch5.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Artículo: &lt;a href="http://dev.mysql.com/tech-resources/articles/mysql-db-design-ch5.pdf"&gt;Joins, Temporary Tables, and Transactions&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;En otro blog encontré que alguien había hecho lo mismo:&lt;br /&gt;&lt;a href="http://www.xaprb.com/blog/2006/05/26/how-to-write-full-outer-join-in-mysql"&gt;http://www.xaprb.com/blog/2006/05/26/how-to-write-full-outer-join-in-mysql&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Todos apuntaban a la misma solución:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;SELECT a&lt;br /&gt;LEFT JOIN b&lt;br /&gt;UNION ALL&lt;br /&gt;SELECT a&lt;br /&gt;RIGHT JOIN b&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Hace unos días me surgió la necesidad del Full Join nuevamente. Estaba con tres inventarios distintos (de tres personas distintas) y quise "unificar" de alguna manera estos, y pasar este nuevo inventario unificado a cada parte. Pero había recordado lo frustrante que me resultó la experiencia anterior, por lo que, cuando estaba por desistir, se me ocurrió probar una última vez, a lo que llegué a un nuevo query.&lt;br /&gt;&lt;br /&gt;Lo que volví a reescribir (no sé si es más efectivo o más agradable estéticamente) me resultó de gran utilidad cuando necesito un Full Join con más de dos tablas! (Todos los ejemplos anteriores mostraban la solución con dos tablas, pero cuando eran más de dos.. uff..)&lt;br /&gt;&lt;br /&gt;Bueno, comencemos.&lt;br /&gt;&lt;br /&gt;Tengo las tres tablas:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE TABLE `one` (&lt;br /&gt;`idone` tinyint unsigned NOT NULL auto_increment,&lt;br /&gt;`host` varchar(16) NOT NULL,&lt;br /&gt;`ip` varchar(16) NOT NULL,&lt;br /&gt;PRIMARY KEY  (`idone`)&lt;br /&gt;)&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;CREATE TABLE `two` (&lt;br /&gt;`idtwo` tinyint unsigned NOT NULL auto_increment,&lt;br /&gt;`host` varchar(16) NOT NULL,&lt;br /&gt;`ip` varchar(16) NOT NULL,&lt;br /&gt;PRIMARY KEY  (`idtwo`)&lt;br /&gt;)&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;CREATE TABLE `three` (&lt;br /&gt;`idthree` tinyint unsigned NOT NULL auto_increment,&lt;br /&gt;`host` varchar(16) NOT NULL,&lt;br /&gt;`ip` varchar(16) NOT NULL,&lt;br /&gt;PRIMARY KEY  (`idthree`)&lt;br /&gt;)&lt;br /&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Cargamos los datos&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;INSERT INTO one (host, ip) VALUES ('linux01', '1.2.3.4');&lt;br /&gt;INSERT INTO one (host, ip) VALUES ('osx2', '1.1.1.1');&lt;br /&gt;INSERT INTO one (host, ip) VALUES ('as400', '-');&lt;br /&gt;INSERT INTO one (host, ip) VALUES ('solaris', '1.1.1.100');&lt;br /&gt;&lt;br /&gt;INSERT INTO two (host, ip) VALUES ('linux-01', '-');&lt;br /&gt;INSERT INTO two (host, ip) VALUES ('osx2', '1.1.1.1');&lt;br /&gt;INSERT INTO two (host, ip) VALUES ('win-fw', '1.2.3.100');&lt;br /&gt;INSERT INTO two (host, ip) VALUES ('solaris', '1.1.1.100');&lt;br /&gt;&lt;br /&gt;INSERT INTO three (host, ip) VALUES ('win-fw', '1.2.2.100');&lt;br /&gt;INSERT INTO three (host, ip) VALUES ('solaris', '1.1.1.100');&lt;br /&gt;INSERT INTO three (host, ip) VALUES ('osx2', '1.1.1.100');&lt;br /&gt;INSERT INTO three (host, ip) VALUES ('linux01', '1.3.2.4');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Como se ven las tablas&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;one&lt;br /&gt;+----+---------+-----------+&lt;br /&gt;| id | host    | ip        |&lt;br /&gt;+----+---------+-----------+&lt;br /&gt;|  1 | linux01 | 1.2.3.4   |&lt;br /&gt;|  2 | osx2    | 1.1.1.1   |&lt;br /&gt;|  3 | as400   | -         |&lt;br /&gt;|  4 | solaris | 1.1.1.100 |&lt;br /&gt;+----+---------+-----------+&lt;br /&gt;&lt;br /&gt;two&lt;br /&gt;+----+----------+-----------+&lt;br /&gt;| id | host     | ip        |&lt;br /&gt;+----+----------+-----------+&lt;br /&gt;|  1 | linux-01 | -         |&lt;br /&gt;|  2 | osx2     | 1.1.1.1   |&lt;br /&gt;|  3 | win-fw   | 1.2.3.100 |&lt;br /&gt;|  4 | solaris  | 1.1.1.100 |&lt;br /&gt;+----+----------+-----------+&lt;br /&gt;&lt;br /&gt;three&lt;br /&gt;+----+---------+-----------+&lt;br /&gt;| id | host    | ip        |&lt;br /&gt;+----+---------+-----------+&lt;br /&gt;|  1 | win-fw  | 1.2.2.100 |&lt;br /&gt;|  2 | solaris | 1.1.1.100 |&lt;br /&gt;|  3 | osx2    | 1.1.1.100 |&lt;br /&gt;|  4 | linux01 | 1.3.2.4   |&lt;br /&gt;+----+---------+-----------+&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;La idea es tener un solo listado de hosts. Para mi caso, quise tenerlo unificado por nombre. Uniendo las tres tablas, todos los hosts que tenemos en total son:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SELECT DISTINCT a.host&lt;br /&gt;FROM (&lt;br /&gt; SELECT idone AS id, host, ip&lt;br /&gt; FROM one&lt;br /&gt; UNION ALL&lt;br /&gt; SELECT idtwo AS id, host, ip&lt;br /&gt; FROM two&lt;br /&gt; UNION ALL&lt;br /&gt; SELECT idthree AS id, host, ip&lt;br /&gt; FROM three&lt;br /&gt;) a&lt;br /&gt;ORDER BY a.host&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;+----------+&lt;br /&gt;| host     |&lt;br /&gt;+----------+&lt;br /&gt;| as400    |&lt;br /&gt;| linux-01 |&lt;br /&gt;| linux01  |&lt;br /&gt;| osx2     |&lt;br /&gt;| solaris  |&lt;br /&gt;| win-fw   |&lt;br /&gt;+----------+&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Lo único que necesitamos hacer es LEFT JOINS a este query! De nuevo, colocamos este query en un FROM en forma de subselect:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SELECT b.host,&lt;br /&gt;one.host AS one, one.ip,&lt;br /&gt;two.host AS two, two.ip,&lt;br /&gt;three.host AS three, three.ip&lt;br /&gt;FROM (&lt;br /&gt;SELECT DISTINCT a.host AS host&lt;br /&gt;FROM (&lt;br /&gt;   SELECT idone AS id, host, ip&lt;br /&gt;   FROM one&lt;br /&gt;   UNION ALL&lt;br /&gt;   SELECT idtwo AS id, host, ip&lt;br /&gt;   FROM two&lt;br /&gt;   UNION ALL&lt;br /&gt;   SELECT idthree AS id, host, ip&lt;br /&gt;   FROM three&lt;br /&gt;) a ORDER BY a.host&lt;br /&gt;) b&lt;br /&gt;LEFT JOIN one ON one.host=b.host&lt;br /&gt;LEFT JOIN two ON two.host=b.host&lt;br /&gt;LEFT JOIN three ON three.host=b.host&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;+----------+---------+-----------+----------+-----------+---------+-----------+&lt;br /&gt;| host     | one     | ip        | two      | ip        | three   | ip        |&lt;br /&gt;+----------+---------+-----------+----------+-----------+---------+-----------+&lt;br /&gt;| as400    | as400   | -         | NULL     | NULL      | NULL    | NULL      |&lt;br /&gt;| linux-01 | NULL    | NULL      | linux-01 | -         | NULL    | NULL      |&lt;br /&gt;| linux01  | linux01 | 1.2.3.4   | NULL     | NULL      | linux01 | 1.3.2.4   |&lt;br /&gt;| osx2     | osx2    | 1.1.1.1   | osx2     | 1.1.1.1   | osx2    | 1.1.1.100 |&lt;br /&gt;| solaris  | solaris | 1.1.1.100 | solaris  | 1.1.1.100 | solaris | 1.1.1.100 |&lt;br /&gt;| win-fw   | NULL    | NULL      | win-fw   | 1.2.3.100 | win-fw  | 1.2.2.100 |&lt;br /&gt;+----------+---------+-----------+----------+-----------+---------+-----------+&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Y el listado sale por sí solo.&lt;br /&gt;&lt;br /&gt;Si necesitáramos agregar otra tabla más al listado, tan solo bastaría con agregar las columnas, una unión más y un LEFT JOIN más al final..&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SELECT b.host,&lt;br /&gt;one.host AS one, one.ip,&lt;br /&gt;two.host AS two, two.ip,&lt;br /&gt;three.host AS three, three.ip,&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;FROM (&lt;br /&gt;SELECT DISTINCT a.host AS host&lt;br /&gt;FROM (&lt;br /&gt;   SELECT idone AS id, host, ip&lt;br /&gt;   FROM one&lt;br /&gt;   UNION ALL&lt;br /&gt;   SELECT idtwo AS id, host, ip&lt;br /&gt;   FROM two&lt;br /&gt;   UNION ALL&lt;br /&gt;   SELECT idthree AS id, host, ip&lt;br /&gt;   FROM three&lt;br /&gt;   UNION ALL&lt;br /&gt;   SELECT idfour AS id, host, ip&lt;br /&gt;   FROM four&lt;br /&gt;&lt;span style="color: rgb(255, 102, 102); font-weight: bold;"&gt;    ...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 102, 102); font-weight: bold;"&gt;    ..&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 102, 102); font-weight: bold;"&gt;    .&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;) a ORDER BY a.host&lt;br /&gt;) b&lt;br /&gt;LEFT JOIN one ON one.host=b.host&lt;br /&gt;LEFT JOIN two ON two.host=b.host&lt;br /&gt;LEFT JOIN three ON three.host=b.host&lt;br /&gt;LEFT JOIN four ON four.host=b.host&lt;br /&gt;&lt;span style="color: rgb(255, 102, 102);"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Probamos agregar una tabla más:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE TABLE `four` (&lt;br /&gt;`idfour` tinyint unsigned NOT NULL auto_increment,&lt;br /&gt;`host` varchar(16) NOT NULL,&lt;br /&gt;`ip` varchar(16) NOT NULL,&lt;br /&gt;PRIMARY KEY  (`idfour`)&lt;br /&gt;)&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;INSERT INTO four (host, ip) VALUES ('solaris', '1.1.1.100');&lt;br /&gt;INSERT INTO four (host, ip) VALUES ('linux', '1.1.2.2');&lt;br /&gt;INSERT INTO four (host, ip) VALUES ('os400', '100.1.1.100');&lt;br /&gt;INSERT INTO four (host, ip) VALUES ('windows', '1.2.2.100');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Y el query queda:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SELECT b.host,&lt;br /&gt;one.host AS one, one.ip,&lt;br /&gt;two.host AS two, two.ip,&lt;br /&gt;three.host AS three, three.ip,&lt;br /&gt;four.host AS four, four.ip&lt;br /&gt;FROM (&lt;br /&gt;SELECT DISTINCT a.host AS host&lt;br /&gt;FROM (&lt;br /&gt;   SELECT idone AS id, host, ip&lt;br /&gt;   FROM one&lt;br /&gt;   UNION ALL&lt;br /&gt;   SELECT idtwo AS id, host, ip&lt;br /&gt;   FROM two&lt;br /&gt;   UNION ALL&lt;br /&gt;   SELECT idthree AS id, host, ip&lt;br /&gt;   FROM three&lt;br /&gt;   UNION ALL&lt;br /&gt;   SELECT idfour AS id, host, ip&lt;br /&gt;   FROM four&lt;br /&gt;) a ORDER BY a.host&lt;br /&gt;) b&lt;br /&gt;LEFT JOIN one ON one.host=b.host&lt;br /&gt;LEFT JOIN two ON two.host=b.host&lt;br /&gt;LEFT JOIN three ON three.host=b.host&lt;br /&gt;LEFT JOIN four ON four.host=b.host&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ahora podemos ver la diferencia entre las cuatro tablas de inventarios de hosts, y en qué difiere cada una:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;+----------+---------+-----------+----------+-----------+---------+-----------+---------+-------------+&lt;br /&gt;| host     | one     | ip        | two      | ip        | three   | ip        | four    | ip          |&lt;br /&gt;+----------+---------+-----------+----------+-----------+---------+-----------+---------+-------------+&lt;br /&gt;| as400    | as400   | -         | NULL     | NULL      | NULL    | NULL      | NULL    | NULL        |&lt;br /&gt;| linux    | NULL    | NULL      | NULL     | NULL      | NULL    | NULL      | linux   | 1.1.2.2     |&lt;br /&gt;| linux-01 | NULL    | NULL      | linux-01 | -         | NULL    | NULL      | NULL    | NULL        |&lt;br /&gt;| linux01  | linux01 | 1.2.3.4   | NULL     | NULL      | linux01 | 1.3.2.4   | NULL    | NULL        |&lt;br /&gt;| os400    | NULL    | NULL      | NULL     | NULL      | NULL    | NULL      | os400   | 100.1.1.100 |&lt;br /&gt;| osx2     | osx2    | 1.1.1.1   | osx2     | 1.1.1.1   | osx2    | 1.1.1.100 | NULL    | NULL        |&lt;br /&gt;| solaris  | solaris | 1.1.1.100 | solaris  | 1.1.1.100 | solaris | 1.1.1.100 | solaris | 1.1.1.100   |&lt;br /&gt;| win-fw   | NULL    | NULL      | win-fw   | 1.2.3.100 | win-fw  | 1.2.2.100 | NULL    | NULL        |&lt;br /&gt;| windows  | NULL    | NULL      | NULL     | NULL      | NULL    | NULL      | windows | 1.2.2.100   |&lt;br /&gt;+----------+---------+-----------+----------+-----------+---------+-----------+---------+-------------+&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;edward.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5839769424182418749-8755167421375019291?l=disemq21.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://disemq21.blogspot.com/feeds/8755167421375019291/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5839769424182418749&amp;postID=8755167421375019291' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5839769424182418749/posts/default/8755167421375019291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5839769424182418749/posts/default/8755167421375019291'/><link rel='alternate' type='text/html' href='http://disemq21.blogspot.com/2009/08/another-mysql-full-join.html' title='Another MySQL Full Join'/><author><name>edward</name><uri>http://www.blogger.com/profile/14900140765215146649</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
