<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Norvys Gonzalez - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Norvys Gonzalez - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 11 May 2026 20:00:41 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/author/norvys/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Mis cursos gratuitos favoritos para aprender estructuras de datos y algoritmos en profundidad ]]>
                </title>
                <description>
                    <![CDATA[ Las estructuras de datos y los algoritmos son algunos de los temas más esenciales para los programadores, tanto para conseguir un trabajo como para hacerlo bien. Un buen conocimiento de las estructuras de datos y los algoritmos es la base para escribir un buen código. Si estás familiarizado con las ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/mis-cursos-gratuitos-favoritos-para-aprender-estructuras-de-datos-y-algoritmos-en-profundidad/</link>
                <guid isPermaLink="false">63e0fc909a3ea706f58b05b9</guid>
                
                    <category>
                        <![CDATA[ Programación ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Norvys Gonzalez ]]>
                </dc:creator>
                <pubDate>Fri, 21 Apr 2023 19:30:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/02/1_bhnjFh3ZeWNlAtg1unulTw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/these-are-the-best-free-courses-to-learn-data-structures-and-algorithms-in-depth-4d52f0d6b35a/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">My favorite free courses to learn data structures and algorithms in depth</a>
      </p><p>Las estructuras de datos y los algoritmos son algunos de los temas más esenciales para los programadores, tanto para conseguir un trabajo como para hacerlo bien. Un buen conocimiento de las estructuras de datos y los algoritmos es la base para escribir un buen código.</p><p>Si estás familiarizado con las estructuras de datos esenciales, como por ejemplo: arreglo, cadenas, listas enlazadas, árboles binarios, mapas, y estructuras de datos avanzadas como tries, y árboles autoequilibrados como los árboles AVL, etc., sabrás cuando usar cuál estructura de datos y calcular el costo de CPU y memoria de tu código.</p><p>Aunque no necesitas escribir tu propia arreglo, lista enlazada, o tabla hash, dado que cada SDK de programación importante los proporciona, por ejemplo: JDK o la librería STL de C++, necesitarás entenderlos para poder utilizarlos en el lugar adecuado.</p><h3 id="el-uso-de-la-estructura-de-datos-correcta-puede-mejorar-dr-sticamente-el-rendimiento-de-un-algoritmo-">El uso de la estructura de datos correcta puede mejorar drásticamente el rendimiento de un algoritmo.</h3><p>Idealmente, todos deberíamos aprender <a href="https://hackernoon.com/10-data-structure-algorithms-and-programming-courses-to-crack-any-coding-interview-e1c50b30b927">estructuras de datos</a> y <a href="https://dzone.com/articles/10-coding-interview-preparation-courses-crack-a-pr">algoritmos</a> en nuestras escuelas y universidades, pero rara vez se cubre. La mayoría de los programadores, incluyéndome a mí, solo conocemos una estructura de datos en nuestros cursos de informática, pero realmente no aprendimos su importancia en el mundo real, y es por eso que no los entendemos mejor.</p><p>Para nosotros, son solo los algoritmos y las estructuras de datos, solo conceptos, no herramientas que puedas utilizar para escribir buenos programas. No sabíamos que Facebook los usaría para almacenar nuestros datos o que Google los usaría para almacenar páginas web y enlaces a consultas de búsqueda.</p><blockquote>De todos modos, nunca es demasiado tarde.</blockquote><p>Si crees que tu conocimiento de estructura de datos no está a la altura o deseas mejorar tu conocimiento de estructura de datos, entonces has venido al lugar correcto.</p><p>Anteriormente, compartí algunos <a href="https://javarevisited.blogspot.com/2016/05/5-free-data-structure-and-algorithm-books-in-java.html#axzz4uXETWjmV">libros en inglés gratuitos para aprender estructuras de datos y algoritmos</a>, y en este artículo, aprenderás sobre algunos de los mejores cursos de estructura de datos y algoritmos que están disponibles de forma gratuita en línea.</p><h3 id="cursos-gratis-para-aprender-estructura-de-datos-y-algoritmos"><strong>Cursos gratis para aprender estructura de datos y algoritmos</strong></h3><p>Aquí está mi lista de algunos de los mejores cursos para aprender estructuras de datos y algoritmos, que además son gratuitos. Muchos programadores piensan que los recursos gratuitos no son buenos, lo cual no es cierto.</p><p>Aunque a veces no igualan la calidad y la cobertura de los recursos pagos, son, de hecho, los mejores recursos para empezar.</p><p>Puedes usar estos cursos para familiarizarse con las estructuras de datos esenciales y aprender algunos conceptos básicos.</p><p>Algunos de ellos son particularmente buenos desde el punto de vista de una entrevista, por lo que puede utilizarlos junto con cualquier libro que estés utilizando para prepararte para su <a href="http://www.java67.com/2018/05/top-75-programming-interview-questions-answers.html">entrevista de trabajo de programación</a>.</p><h2 id="curso-1-conceptos-de-estructura-de-datos-en-c"><strong>Curso #1: </strong>Conceptos de estructura de datos en C</h2><p>Este es otro curso gratuito de capacitación en línea sobre algoritmos y estructuras de datos, cuyo objetivo es enseñar estructuras de datos básicas en la programación de computadoras.</p><p>Las estructuras de datos que se enseñan en el curso incluyen <a href="http://www.java67.com/2013/08/ata-structures-in-java-programming-array-linked-list-map-set-stack-queue.html">Stack</a>, <a href="http://javarevisited.blogspot.sg/2017/03/difference-between-stack-and-queue-data-structure-in-java.html#axzz4rZnFiEOx">Queue </a>y <a href="https://javarevisited.blogspot.com/2015/02/simple-junit-example-unit-tests-for-linked-list-java.html">Listas enlazadas</a>, empleando el lenguaje de programación C.</p><p>El objetivo principal de esto es hacer que los estudiantes y los ingenieros de software visualicen cómo funcionan las diferentes estructuras de datos.</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/9KAnoe0SwLrdwMWSxZvutFKzyxq959oVVyZ7" class="kg-image" alt="9KAnoe0SwLrdwMWSxZvutFKzyxq959oVVyZ7" width="400" height="287" loading="lazy"></figure><p>Este no es un curso exhaustivo, pero aprenderás sobre <a href="https://javarevisited.blogspot.com/2017/03/how-to-implement-stack-in-java-using-array-example.html">Stack</a>, Queue y <a href="https://javarevisited.blogspot.com/2017/03/how-to-reverse-linked-list-in-java-using-iteration-and-recursion.html#axzz5bAq1c3jf">listas enlazadas</a>.</p><p>En resumen, es un gran curso para programadores nuevos en estructuras de datos y para aquellos que acaban de aprender un lenguaje de programación y quieren aprender los conceptos básicos de cómo funcionan las estructuras de datos.</p><h2 id="curso-2-algoritmos-parte-1-coursera"><strong>Curso #2: </strong>Algoritmos Parte 1 - Coursera</h2><p>Esta es la <a href="https://www.coursera.org/learn/algorithms-part1">primera parte</a> de una serie de cursos de dos partes que cubren algoritmos y estructuras de datos en Coursera por Robert Sedgewick.</p><p>En esta parte, aprenderá estructuras de datos esenciales como <a href="http://javarevisited.blogspot.sg/2017/07/top-10-linked-list-coding-questions-and.html#axzz4xXS86IVo">listas enlazadas</a>, <a href="https://javarevisited.blogspot.com/2017/03/difference-between-stack-and-queue-data-structure-in-java.html" rel="noopener">stacks</a>, queues, <a href="https://javarevisited.blogspot.com/2015/10/how-to-implement-binary-search-tree-in-java-example.html">árboles binarios</a>, y <a href="http://javarevisited.blogspot.sg/2011/02/how-hashmap-works-in-java.html#axzz5B9NXhuQw">tablas hash</a>, y algoritmos de búsqueda y clasificación como: <a href="https://javarevisited.blogspot.com/2017/04/recursive-binary-search-algorithm-in-java-example.html" rel="noopener">binary search</a>, <a href="https://javarevisited.blogspot.com/2014/08/quicksort-sorting-algorithm-in-java-in-place-example.html" rel="noopener">quicksort</a>, <a href="http://www.java67.com/2018/03/mergesort-in-java-algorithm-example-and.html" rel="noopener">mergesort</a>, <a href="https://javarevisited.blogspot.com/2014/12/insertion-sort-algorithm-in-java-to-array-example.html" rel="noopener">insertion sort</a>, etc.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/Uqip9-SbrXSJg53ERcVRpQIvCRwBl9MQsozM" class="kg-image" alt="Uqip9-SbrXSJg53ERcVRpQIvCRwBl9MQsozM" width="400" height="252" loading="lazy"><figcaption><a href="http://bit.ly/algorithms-part1" rel="noopener" target="_blank" title="" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 17.6px; vertical-align: baseline; background-color: transparent; color: var(--gray90); text-decoration: underline; cursor: pointer; word-break: break-word;">Algorithms Part 1</a></figcaption></figure><p>También aprenderás sobre las estructuras de datos centrales y los algoritmos utilizados en las aplicaciones cotidianas y comprenderá las ventajas y desventajas involucradas en la elección de cada estructura de datos junto con los algoritmos de <a href="http://www.java67.com/2017/05/binary-tree-post-order-traversal-in-java-without-recursion.html">recorrido</a>, recuperación y actualización.</p><p>Todas las características de este curso están disponibles de forma gratuita, pero no ofrece un certificado al finalizar.</p><h3 id="curso-3-algoritmos-parte-2"><strong><strong><strong>Curs</strong></strong>o<strong><strong> #3: </strong></strong></strong>Algoritmos - Parte 2</h3><p>Esta es la <a href="https://www.coursera.org/learn/algorithms-part2">segunda parte</a> de una serie de dos partes de cursos gratuitos en línea de Coursera que cubren estructuras de datos y algoritmos de Robert Sedgewick y Kevin Wayne, ambos profesores de Ciencias de la Computación.</p><p>Robert Sedgewick también es el autor del libro <strong><strong><a href="http://www.amazon.com/Algorithms-4th-Edition-Robert-Sedgewick/dp/032157351X?tag=javamysqlanta-20" rel="noopener">Algoritmos 4th Edition</a></strong></strong> , uno de los libros más populares sobre algoritmos para desarrolladores de Java.</p><p>En esta <a href="https://www.coursera.org/learn/algorithms-part2">parte</a>, aprenderás sobre los algoritmos de procesamiento de cadenas y gráficos.</p><p>También aprenderás algunas estructuras de datos y algoritmos avanzados empleados en el desarrollo de aplicaciones.</p><p>Hablando de la prueba social, tanto <a href="https://www.coursera.org/learn/algorithms-part1">Algoritmos Parte 1</a> y &nbsp;<a href="https://www.coursera.org/learn/algorithms-part2">Algoritmos Parte 2</a> son cursos altamente recomendados y tienen críticas y calificaciones impresionantes.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/-ClYQqg03sCkaKTze2IFx-gVZ1rJ9oxXbiM3" class="kg-image" alt="-ClYQqg03sCkaKTze2IFx-gVZ1rJ9oxXbiM3" width="225" height="225" loading="lazy"><figcaption><a href="http://bit.ly/algorithms-part2" rel="noopener" target="_blank" title="" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 17.6px; vertical-align: baseline; background-color: transparent; color: var(--gray90); text-decoration: underline; cursor: pointer; word-break: break-word;">Algorithms — Part 2</a></figcaption></figure><h2 id="curso-4-estructuras-de-datos-en-java"><strong>Curso #4. </strong>Estructuras de datos en Java</h2><p>Este es un c<a href="http://bit.ly/2zLGO3B">urso introductorio en línea sobre estructuras de datos</a>, algoritmos y análisis de complejidad. Te enseñará el diseño, la implementación y el análisis de estructuras de datos básicas utilizando el lenguaje Java.</p><p>La mejor parte de este <a href="https://www.udemy.com/course/data-structures-part-1-lognacademy/?LSNPUBID=JVFxdTr9V80&amp;ranEAID=JVFxdTr9V80&amp;ranMID=39197&amp;ranSiteID=JVFxdTr9V80-1oRgNI5PlhJsM0hhk7_kWg&amp;utm_medium=udemyads&amp;utm_source=aff-campaign">curso</a> es la cantidad de ejemplos prácticos y que se enfoca en la intuición en lugar de fórmulas y pruebas matemáticas.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/BidoQMlvn0BpD8u95vR7IaGcorlUbo87lAMw" class="kg-image" alt="BidoQMlvn0BpD8u95vR7IaGcorlUbo87lAMw" width="400" height="225" loading="lazy"><figcaption><a href="http://bit.ly/2zLGO3B" rel="noopener" target="_blank" title="" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 17.6px; vertical-align: baseline; background-color: transparent; color: var(--gray90); text-decoration: underline; cursor: pointer; word-break: break-word;"><strong style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 17.6px; vertical-align: baseline; color: var(--gray85);">Data Structure in Java</strong></a></figcaption></figure><p>El <a href="http://bit.ly/2zLGO3B">curso</a> proporciona una buena introducción al “análisis de complejidad”, que permite detectar un programa con un rendimiento deficiente (y excelente), incluso sin necesidad de ejecutarlo.</p><p>Eso es todo acerca de algunos <strong><strong>curs</strong>o<strong>s </strong>gratuitos de estructuras de datos algoritmos </strong>disponibles en línea. Puedes usar estos cursos para aprender estructuras de datos y algoritmos a su propio ritmo.</p><p>Puede que no todos sean exhaustivos, pero proporcionan una buena introducción. Una vez que complete estos cursos, puede elegir un buen libro como <strong><a href="http://javarevisited.blogspot.com/2015/07/5-data-structure-and-algorithm-books-best-must-read.html#axzz54hiGw48b">Introducción a los Algoritmos</a></strong><a href="http://javarevisited.blogspot.com/2015/07/5-data-structure-and-algorithm-books-best-must-read.html#axzz54hiGw48b" rel="noopener"> </a>para complementar aún más su conocimiento.</p><h2 id="curso-5-estructuras-de-datos-de-f-ciles-a-avanzadas"><strong>Curso #5. </strong>Estructuras de datos de fáciles a avanzadas</h2><p>Actualización: este curso ya no es gratuito, pero es un gran curso y puede valer la pena para ti. Este <a href="https://click.linksynergy.com/deeplink?id=JVFxdTr9V80&amp;mid=39197&amp;murl=https%3A%2F%2Fwww.udemy.com%2Fintroduction-to-data-structures%2F">curso</a> de estructura de datos y algoritmos de Udemy son para todas aquellas personas que desean aprender estructuras de datos desde un nivel absolutamente básico hasta avanzado.</p><p>Este <a href="https://click.linksynergy.com/deeplink?id=JVFxdTr9V80&amp;mid=39197&amp;murl=https%3A%2F%2Fwww.udemy.com%2Fintroduction-to-data-structures%2F">curso</a> no espera que tenga ningún conocimiento previo de estructuras de datos, pero un conocimiento previo básico de <a href="http://www.java67.com/2018/08/top-10-free-java-courses-for-beginners-experienced-developers.html">Java</a> es útil.</p><p>El autor @William Fiset es ingeniero de software en <a href="https://javarevisited.blogspot.com/2012/01/google-interview-questions-answers-top.html">Google</a> y ex finalista mundial de <strong>ACM-ICPC</strong> y tiene excelentes habilidades de programación informática y resolución de problemas.</p><p>Hablando de prueba social, el <a href="https://click.linksynergy.com/deeplink?id=JVFxdTr9V80&amp;mid=39197&amp;murl=https%3A%2F%2Fwww.udemy.com%2Fintroduction-to-data-structures%2F">curso</a> tiene más de 25 000 estudiantes y una calificación promedio de 4.1 de 683, lo cual es impresionante.</p><p>En resumen, es una guía completa para aprender todo lo que hay que saber sobre las estructuras de datos.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/4-E1RXoSCW8fNivg1wkYVuFmvzPzhkE3uVIF" class="kg-image" alt="4-E1RXoSCW8fNivg1wkYVuFmvzPzhkE3uVIF" width="392" height="400" loading="lazy"><figcaption>Easy to Advanced Data Structures</figcaption></figure><p>Este también es un curso ideal para estudiantes de ciencias de la computación y profesionales de software en activo que desean aprender estructuras de datos y algoritmos desde una perspectiva de entrevista.</p><p>Entonces, si estás buscando un trabajo en compañías basadas en productos como <a href="http://javarevisited.blogspot.sg/2016/01/top-20-amazon-and-google-programming-interview-questions.html" rel="noopener">Amazon</a>, <a href="http://javarevisited.blogspot.com/2012/01/google-interview-questions-answers-top.html#axzz54hiGw48b" rel="noopener">Google</a>, <a href="http://javarevisited.blogspot.sg/2015/12/30-microsoft-interview-questions-for-software-development-engineers.html" rel="noopener">Microsoft</a>, o Facebook, puedes usar este curso para poner en marcha tu preparación.</p><h4 id="notas-de-cierre"><strong>Notas de cierre</strong></h4><p>Gracias. Llegaste al final del artículo. ¡Buena suerte en tu camino para convertirte en programador! Ciertamente, no será fácil, pero al seguir estos cursos, estarás un paso más cerca de dominar la estructura de datos y los algoritmos que otros.</p><p>Si te gustó este artículo, compártelo con tus amigos y colegas, ¡y no olvides seguir a <a href="https://twitter.com/javinpaul">javinpaul</a> en Twitter!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Tutorial de combinaciones (joins) en SQL: Cross join, full outer join, inner join, left join, y right join. ]]>
                </title>
                <description>
                    <![CDATA[ Los joins o combinaciones de SQL permiten que nuestros sistemas de administración de base de datos relacionales estén bien "relacionados". Los joins o combinaciones nos permiten reconstruir de nuevo nuestras tablas de base de datos separadas en relaciones que impulsan nuestras aplicaciones. En este artículo, hablaremos de cada uno de ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/tutorial-de-uniones-en-sql/</link>
                <guid isPermaLink="false">6328c00070a5cb0907d694b1</guid>
                
                    <category>
                        <![CDATA[ SQL ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Norvys Gonzalez ]]>
                </dc:creator>
                <pubDate>Tue, 20 Dec 2022 21:28:20 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/09/5f9c98fc740569d1a4ca1d31--1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/sql-joins-tutorial/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">SQL Joins Tutorial: Cross Join, Full Outer Join, Inner Join, Left Join, and Right Join.</a>
      </p><p>Los joins o combinaciones de SQL permiten que nuestros sistemas de administración de base de datos relacionales estén bien "relacionados"<em><em>.</em></em></p><p>Los joins o combinaciones nos permiten reconstruir de nuevo nuestras tablas de base de datos separadas en relaciones que impulsan nuestras aplicaciones.</p><p>En este artículo, hablaremos de cada uno de los diferentes tipos de joins o combinaciones de SQL y como usarlas.</p><p>Lo que cubriremos:</p><ul><li>¿Qué es un join o combinación de SQL?</li><li>Configurando tu base de datos</li><li><code>CROSS JOIN</code></li><li>Configurando nuestra data ejemplo (directorios y películas)</li><li><code>FULL OUTER JOIN</code></li><li><code>INNER JOIN</code></li><li><code>LEFT JOIN</code> / <code>RIGHT JOIN</code></li><li>Filtrar usando <code>LEFT JOIN</code></li><li>Múltiples joins o combinaciones</li><li>Joins o combinaciones con condiciones extra</li><li>La verdad sobre escribir queries con joins o combinaciones</li></ul><p>(<em>Alerta de spoiler</em>: cubriremos cinco diferentes tipos—pero solamente necesitas conocer dos de ellos!)</p><h2 id="-qu-es-un-join-o-combinaci-n-en-sql"><strong>¿Qué es un join o combinación en SQL?</strong></h2><p>Un <strong><strong>join</strong></strong> es una operación que combina dos filas juntas en una fila.</p><p>Estas filas usualmente pertenecen a dos tablas diferentes —pero no necesariamente tiene que ser así.</p><p>Antes de ver como escribir un <em>join</em>, veamos como se vería su resultado.</p><p>Tomemos como ejemplo un sistema que almacena información acerca de sus usuarios y sus direcciones.</p><p>Las filas de la tabla que almacena la información del usuario se vería así:</p><pre><code class="language-español"> id |     nombre     |        email        | edad
----+--------------+---------------------+-----
  1 | John Smith     | johnsmith@gmail.com |  25
  2 | Jane Doe       | janedoe@Gmail.com   |  28
  3 | Xavier Wills   | xavier@wills.io     |  3
...
(7 filas)</code></pre><p>Y las filas de la tabla que almacena direcciones podría verse así:</p><pre><code class="language-español"> id |      calle        |     ciudad    | estado| id_usuario
----+-------------------+---------------+-------+---------
  1 | 1234 Main Street  | Oklahoma City | OK    |       1
  2 | 4444 Broadway Ave | Oklahoma City | OK    |       2
  3 | 5678 Party Ln     | Tulsa         | OK    |       3
(3 rows)</code></pre><p>Podríamos escribir por separado consultas que nos traiga tanto información relacionada con los usuarios como la información de la dirección — pero idealmente podemos escribir <em>una consulta</em> y recibir todos los usuarios y las direcciones al mismo tiempo.</p><p>¡Esto es exactamente lo que nos permiten hacer los joins!</p><p>Veremos como escribir estos joins pronto, pero si combinamos nuestra información del usuario a la información de dirección conseguiremos un resultado como este:</p><pre><code class="language-español"> id |     nombre     |        email        | edad | id |      calle      |    ciudad      | estado | id_usuario
----+--------------+---------------------+-----+----+-------------------+---------------+-------+---------
  1 | John Smith   | johnsmith@gmail.com |  25 |  1 | 1234 Main Street  | Oklahoma City | OK    |       1
  2 | Jane Doe     | janedoe@Gmail.com   |  28 |  2 | 4444 Broadway Ave | Oklahoma City | OK    |       2
  3 | Xavier Wills | xavier@wills.io     |  35 |  3 | 5678 Party Ln     | Tulsa         | OK    |       3
(3 filas)
</code></pre><p>Aquí vemos todos los usuarios y sus direcciones en un buen conjunto de resultadoa.</p><p>Además de producir un conjunto de resultado combinado, otro uso importante de los <em>joins</em> es obtener información adicional contra la que podemos filtrar.</p><p>Por ejemplo, si queremos enviar un correo físico a todos los usuarios que viven en la ciudad de Oklahoma, podríamos usar el conjunto de resultado combinado y filtrarlo basado en la columna ciudad.</p><p>Ahora que sabemos el propósito de los Joins, ¡empecemos escribiendo algunos!</p><h2 id="configurando-tu-base-de-datos"><strong>Configurando tu base de datos</strong></h2><p>Antes de que podamos escribir nuestras consultas necesitamos configurar nuestra base de datos.</p><p>Para estos ejemplos estaremos usando PostgreSQL, pero las consultas y conceptos mostrados aquí serán facilmente traducidos a cualquier sistema moderno de base de datos (como MySQL, SQL Server, etc.).</p><p>Para trabajar con nuestra base de datos en &nbsp;PostgreSQL, podemos usar <code><a href="https://www.postgresql.org/docs/current/app-psql.html">psql</a></code>—el programa interactivo de línea de comandos de PostgreSQL. Si tienes otro cliente de base de datos con el que disfrutes trabajar puedes usarlo también.</p><p>Para comenzar vamos a crear nuestra base de datos. Con el PostgreSQL <a href="https://www.postgresql.org/download/">y</a>a instalado, corremos el comando <code>createdb &lt;nombre de la base de datos&gt;</code> en nuestra terminal para crear nuestra base de datos. Llamé a la mia <code>fcc</code>:</p><pre><code class="language-bash">$ createdb fcc
</code></pre><p>Ahora iniciemos la consola interactiva usando el comando <code>psql</code> y nos conectamos a la base de datos que acabamos de crear usando <code>\c &lt;nombre de la base de datos&gt;</code>:</p><pre><code class="language-bash">$ psql
psql (11.5)
Type "help" for help.

john=# \c fcc
You are now connected to database "fcc" as user "john".
fcc=#
</code></pre><blockquote><strong><strong>Not</strong>a<strong>:</strong></strong> Limpié la salida de <code>psql</code> en estos ejemplos para hacerlos más fáciles de leer, así que no te preocupes si la salida que te muestro aquí no es exactamente igual a la que estás viendo en tu terminal.</blockquote><p>Te recomiendo que hagas estos ejemplos conmigo y que corras estas consultas tu mismo. Aprenderás y recordarás mucho más trabajando sobre estos ejemplos en lugar de solo leerlos. &nbsp;</p><p>¡Ahora veamos las combinaciones o <em>joins</em>!</p><h2 id="cross-join"><strong><code>CROSS JOIN</code></strong></h2><p>Los joins más simples que podemos hacer son los &nbsp;<code>CROSS JOIN</code> o <em><em>"</em>Producto cartesiano<em>."</em></em></p><p>Este join toma cada fila de una tabla y la une a cada fila de otra tabla.</p><p>Si tenemos dos listas —una que contiene <code>1, 2, 3</code> y otra que contiene <code>A, B, C</code>—el producto cartesiano de las dos listas sería:</p><pre><code>1A, 1B, 1C
2A, 2B, 2C
3A, 3B, 3C
</code></pre><p>Cada valor de la primera lista es emparejado con cada valor de la segunda lista.</p><p>Escribamos este mismo ejemplo como un query en SQL.</p><p>Primero creamos dos tablas muy simples e insertemos algunos datos en ellas:</p><pre><code class="language-sql">CREATE TABLE letras(
  letra TEXT
);

INSERT INTO letras(letra) VALUES ('A'), ('B'), ('C');

CREATE TABLE numeros(
  num TEXT
);

INSERT INTO numeros(num) VALUES (1), (2), (3);
</code></pre><p>Nuestras dos tablas, <code>letras</code> y <code>numeros</code>, solo tienen una columna: un campo de texto simple.</p><p>Ahora vamos a combinarlas con <code>CROSS JOIN</code>:</p><pre><code class="language-sql">SELECT *
FROM letras
CROSS JOIN numeros;
</code></pre><pre><code> letra | num
--------+--------
 A      | 1
 A      | 2
 A      | 3
 B      | 1
 B      | 2
 B      | 3
 C      | 1
 C      | 2
 C      | 3
(9 filas)

</code></pre><p>Este es el &nbsp;join mas simple que podemos hacer —pero aún en este simple ejemplo podemos ver como trabajan los joins: las dos filas separadas (una de <code>letras</code> y otra de <code>numeros</code>) han sido <em>combinadas</em> para formar una fila.</p><p>Mientras este tipo de join es discutido como un mero ejemplo académico, tiene al menos un buen caso de uso: rangos de fechas.</p><h3 id="cross-join-con-rangos-de-fecha"><strong><code>CROSS JOIN</code> con rangos de fecha</strong></h3><p>Un buen caso de uso del <code>CROSS JOIN</code> es tomar cada fila de una tabla y aplicarla a todos los días dentro de un rango de fecha.</p><p>Digamos por ejemplo que estabas creando una aplicación que hiciera seguimiento a tareas diarias —cosas como cepillarte los dientes, comer tu desayuno, o ducharte.</p><p>Si quisieras generar un registro de <em>cada tarea diaria y por cada día de la semana pasada</em>, podrías usar un <code>CROSS JOIN</code> contra un rango de fechas.</p><p>Para hacer este rango de fechas, podemos usar la &nbsp;función <code><a href="https://www.postgresql.org/docs/current/functions-srf.html">generate_series</a></code>:</p><pre><code class="language-sql">SELECT generate_series(
  (CURRENT_DATE - INTERVAL '5 day'),
  CURRENT_DATE,
  INTERVAL '1 day'
)::DATE AS dia;
</code></pre><p>La función <code>generate_series</code> toma tres parámetros.</p><p>El primer parámetro es el valor inicial. En este ejemplo estamos usando <code>CURRENT_DATE - INTERVAL '5 day'</code>. Esto devuelve la fecha actual menos cinco días —o lo que es lo mismo a "hace cinco días."</p><p>El segundo parámetro es la fecha actual (<code>CURRENT_DATE</code>).</p><p>El tercer parámetro es el "intervalo de paso"—o cuánto queremos incrementar el valor cada vez. Dado que estas son tareas diarias, usaremos el intervalo de un día (<code>INTERVAL '1 day'</code>).</p><p>Poniéndolo todo junto, esto genera una serie de fechas que comienzan hace cinco días, terminan hoy y van un día a la vez.</p><p>Finalmente, eliminamos la porción de tiempo al convertir la salida de estos valores a una fecha usando <code>::DATE</code>, y le asignamos un alias a esta columna usando <code>AS dia</code> para hacer la salida un poco más agradable.</p><p>El resultado de esta consulta son los últimos cinco días más hoy:</p><pre><code>    dia
------------
 2020-08-19
 2020-08-20
 2020-08-21
 2020-08-22
 2020-08-23
 2020-08-24
(6 filas)
</code></pre><p>Volviendo a nuestro ejemplo de tareas por día, creemos una tabla simple que incluya las tareas que queremos completar e insertemos algunas tareas:</p><pre><code class="language-sql">CREATE TABLE tareas(
  nombre TEXT
);

INSERT INTO tareas(nombre) VALUES
('Lavar dientes'),
('Comer desayuno'),
('Ducharse'),
('Vestirse');
</code></pre><p>Nuestra tabla<code>tareas</code> solo tiene una columna, <code>nombre</code>, e insertamos cuatro tareas en esta tabla.</p><p>Ahora hagamos<code>CROSS JOIN</code> a nuestras tareas con la consulta para generar las fechas :</p><pre><code class="language-sql">SELECT
  tareas.nombre,
  dates.day
FROM tareas
CROSS JOIN
(
  SELECT generate_series(
    (CURRENT_DATE - INTERVAL '5 day'),
    CURRENT_DATE,
    INTERVAL '1 day'
  )::DATE	AS dia
) AS fechas
</code></pre><p>(Dado que nuestra consulta de generación de fechas no es una tabla real, simplemente la escribimos como una subconsulta)</p><p>A partir de esta consulta, devolvemos el nombre de la tarea y el día, y el conjunto de resultados se ve así:</p><pre><code>     nombre      |    dia
---------------+------------
 Lavar dientes   | 2020-08-19
 Lavar dientes   | 2020-08-20
 Lavar dientes   | 2020-08-21
 Lavar dientes   | 2020-08-22
 Lavar dientes   | 2020-08-23
 Lavar dientes   | 2020-08-24
 Comer desayuno  | 2020-08-19
 Comer desayuno  | 2020-08-20
 Comer desayuno  | 2020-08-21
 Comer desayuno  | 2020-08-22
 ...
 (24 filas)
</code></pre><p>Como esperábamos, obtenemos una fila para cada tarea por cada día en nuestro rango de fechas.</p><p>El <code>CROSS JOIN</code> es el más simple join que podemos hacer, pero para ver los siguientes tipos, necesitaremos una configuración de tabla más realista.</p><h2 id="creando-directorios-y-pel-culas"><strong>Creando directorios y películas</strong></h2><p>Para ilustrar los siguientes tipos de combinaciones o joins, usaremos el ejemplo de <em>películas</em> y <em>directorios de películas<em>.</em></em></p><p>En esta situación, una película tiene un director, pero no se requiere que una película tenga un director —imagínate que se anuncia una nueva película, pero la elección del director aún no se ha confirmado.</p><p>Nuestra tabla<code>directorios</code> almacenará el nombre de cada director, y la tabla <code>películas</code> almacenará el nombre de la película así como una referencia al director de la película (si tuviera uno).</p><p>Vamos a crear esas dos tablas e insertar algunos datos en ellas:</p><pre><code class="language-sql">CREATE TABLE directorios(
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL
);

INSERT INTO directorios(name) VALUES
('John Smith'),
('Jane Doe'),
('Xavier Wills')
('Bev Scott'),
('Bree Jensen');

CREATE TABLE peliculas(
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  director_id INTEGER REFERENCES directorios 
);

INSERT INTO peliculas(name, director_id) VALUES
('Pelicula 1', 1),
('Pelicula 2', 1),
('Pelicula 3', 2),
('Pelicula', NULL),
('Pelicula', NULL);
</code></pre><p>Tenemos cinco directorios, cinco películas, y tres de esas películas tienen directorios asignados. Director ID 1 tiene dos películas, y director ID 2 tiene una.</p><h2 id="full-outer-join"><strong><code>FULL OUTER JOIN</code></strong></h2><p>Ahora que tenemos algunos datos con los que trabajar, veamos el <code>FULL OUTER JOIN</code>.</p><p>Un<code>FULL OUTER JOIN</code> tiene algunas similitudes con un <code>CROSS JOIN</code>, pero tiene un par de diferencias clave.</p><p>La primera diferencia es que un <code>FULL OUTER JOIN</code> requiere una <strong>condición de combinación<strong>.</strong></strong></p><p>Una condición de combinación especifica cómo se relacionan entre sí las filas entre las dos tablas y según qué criterios deben unirse.</p><p>En nuestro ejemplo, nuetras tabla <code>películas</code> tiene una referencia al director a través de la columna <code>director_id</code>, y esta columna coincide con la columna <code>id</code> de la tabla <code>directors</code>. Estas son las dos columnas que usaremos como nuestra condición de combinación.</p><p>Así es como escribimos esta combinación entre nuestras dos tablas:</p><pre><code class="language-sql">SELECT *
FROM peliculas
FULL OUTER JOIN directorios
  ON director.id = peliculas.director_id;
</code></pre><p>Observe la condición de combinación que especificamos que hace coincidir la película con su director: <code>ON peliculas.director_id = directorios.id</code>.</p><p>Nuestro conjunto de resultados parece una especie de producto cartesiano extraño:</p><pre><code>  id  |  nombre   | director_id |  id  |     nombre
------+---------+-------------+------+--------------
    1 | Pelicula 1 |           1 |    1 | John Smith
    2 | Pelicula 2 |           1 |    1 | John Smith
    3 | Pelicula 3 |           2 |    2 | Jane Doe
    4 | Pelicula 4 |        NULL | NULL | NULL
    5 | Pelicula 5 |        NULL | NULL | NULL
 NULL | NULL       |        NULL |    5 | Bree Jensen
 NULL | NULL       |        NULL |    4 | Bev Scott
 NULL | NULL       |        NULL |    3 | Xavier Wills
(8 filas)
</code></pre><p>Las primeras filas que vemos son aquellas en las que la película tenía un director, y nuestra condición de combinación se evaluó como verdadera.</p><p>Sin embargo, después de esas filas, vemos cada una de las filas restantes <em>de cada tabla</em>—pero con valores<code>NULL</code> &nbsp;donde la otra tabla no tiene una coincidencia.</p><blockquote><strong><strong>Note:</strong></strong> Si no estás familiarizado con valores <code>NULL</code> , <a href="https://www.freecodecamp.org/news/sql-operators-tutorial/#dealing-with-missing-data-null-">ve mi explicación aqui </a>en este tutorial de operadores de SQL.</blockquote><p>Aquí también vemos otra diferencia entre el <code>CROSS JOIN</code> y el<code>FULL OUTER JOIN</code>. Un <code>FULL OUTER JOIN</code> devuelve una fila distinta de cada tabla—a diferencia del <code>CROSS JOIN</code> que tiene múltiples.</p><h2 id="inner-join"><strong><code>INNER JOIN</code></strong></h2><p>El siguiente tipo de join, <code>INNER JOIN</code>, es uno de los tipos de join más utilizados.</p><p>Un inner join <strong>solo devuelve filas donde la condición de join es verdadera<strong>.</strong></strong></p><p>En nuestro ejemplo, un inner join entre nuestras tablas <code>peliculas</code> y <code>directorios</code> solo devolvería registros en los que a la película se le haya asignado un director.</p><p>La sintaxis es básicamente la misma que antes:</p><pre><code class="language-sql">SELECT *
FROM peliculas
INNER JOIN directorios
  ON directorios.id = peliculas.director_id;
</code></pre><p>Nuestro resultado muestra las tres películas que tienen un director:</p><pre><code> id |  nombre   | director_id | id |    nombre
----+---------+-------------+----+------------
  1 | Pelicula 1 |           1 |  1 | John Smith
  2 | Pelicula 2 |           1 |  1 | John Smith
  3 | Pelicula 3 |           2 |  2 | Jane Doe
(3 filas)
</code></pre><p>Dado que un inner join solo incluye filas que coinciden con la condición del join, <em>el orden de las dos tablas en el join no importa<em>.</em></em></p><p>Si invertimos el orden de las tablas en la consulta, obtenemos el mismo resultado:</p><pre><code class="language-sql">SELECT *
FROM directorios
INNER JOIN peliculas
  ON peliculas.director_id = directorios.id;
</code></pre><pre><code> id |    nombre    | id |  nombre   | director_id
----+------------+----+---------+-------------
  1 | John Smith |  1 | Pelicula 1 |           1
  1 | John Smith |  2 | Pelicula 2 |           1
  2 | Jane Doe   |  3 | Pelicula 3 |           2
(3 filas)
</code></pre><p>Dado que enumeramos la tabla &nbsp;<code>directorios</code> primero en esta consulta y selecciona todas las columnas (<code>SELECT *</code>), vemos los datos de la columna <code>directorios</code> primero y luego las columnas de <code>peliculas</code>—pero el resultado es el mismo.</p><p>Esta es una propiedad útil de los inner joins, pero no es cierta para todos los tipos de joins—como nuestro próximo tipo de join.</p><h2 id="left-join-right-join"><strong><code>LEFT JOIN</code> / <code>RIGHT JOIN</code></strong></h2><p>Los siguientes tipos de joins usan un modificador (<code>LEFT</code> or <code>RIGHT</code>) que afecta qué datos de la tabla se incluyen en el conjunto de resultados.</p><blockquote><strong><strong>Not</strong>a<strong>:</strong></strong> el <code>LEFT JOIN</code> y<code>RIGHT JOIN</code> también puede ser referido como <code>LEFT OUTER JOIN</code> y <code>RIGHT OUTER JOIN</code>.</blockquote><p>Estos joins se utilizan en consultas en las que queremos devolver todos los datos de una tabla en particular y, <em>si existe</em>, los datos de la tabla asociada también.</p><p>Si los datos asociados no existen, aún recuperamos todos los datos de la tabla "primaria".</p><p>Es una consulta de información sobre algo en particular e información adicional si esta información adicional existe.</p><p>Esto será simple de entender con un ejemplo. Vamos a encontrar todas las películas y sus directorios, pero sin importar si tienen director o no—esto es adicional:</p><figure class="kg-card kg-code-card"><pre><code class="language-sql">SELECT *
FROM peliculas
LEFT JOIN directorios
  ON directorios.id = peliculas.director_id;
</code></pre><figcaption>pe</figcaption></figure><p>La consulta sigue nuestro mismo patrón que antes—acabamos de especificar el join como un <code>LEFT JOIN</code>.</p><p>En este ejemplo, la tabla <code>peliculas</code> es la tabla de la "derecha".</p><p>Si escribimos la consulta en una línea, hace que esto sea un poco más fácil de ver:</p><pre><code class="language-sql">... FROM peliculas LEFT JOIN directorios ...
</code></pre><p><strong>Un<strong> left join </strong>devuelve todos los datos de la tabla de la<strong> "</strong>izquierda<strong>".</strong></strong></p><p>Un left join devuelve cualquier fila de la tabla "derecha" &nbsp;<strong>que coincida con la condición del join.</strong></p><p>Las filas de la tabla de la "derecha" &nbsp;<strong>que no coinciden con la condición del join se devuelven como</strong><code><strong><strong>NULL</strong></strong></code><strong><strong>.</strong></strong></p><pre><code> id |  nombre   | director_id |  id  |    nombre
----+---------+-------------+------+------------
  1 | Pelicula 1 |           1 |    1 | John Smith
  2 | Pelicula 2 |           1 |    1 | John Smith
  3 | Pelicula 3 |           2 |    2 | Jane Doe
  4 | Pelicula 4 |        NULL | NULL | NULL
  5 | Pelicula 5 |        NULL | NULL | NULL
(5 filas)
</code></pre><p>Mirando ese conjunto de resultados, podemos ver por qué este tipo de join es útil para el tipo de consultas <em><em>"</em></em>todo esto y, si existe, algo de eso<em><em>"</em></em> .</p><h3 id="right-join"><strong><code>RIGHT JOIN</code></strong></h3><p>El <code>RIGHT JOIN</code> trabaja exactamente como <code>LEFT JOIN</code>—excepto que las reglas sobre las dos tablas están invertidas.</p><p>En un right join, se devuelven todas las filas de la tabla "derecha" . La tabla &nbsp;"izquierda" se devuelve condicionalmente en función de la condición del join.</p><p>Usemos la misma consulta que arriba, pero sustituyamos <code>LEFT JOIN</code> por <code>RIGHT JOIN</code>:</p><pre><code class="language-sql">SELECT *
FROM peliculas
RIGHT JOIN directorios
  ON directorios.id = peliculas.director_id;
</code></pre><pre><code>  id  |  nombre   | director_id | id |     nombre
------+---------+-------------+----+--------------
    1 | Pelicula 1 |           1 |  1 | John Smith
    2 | Pelicula 2 |           1 |  1 | John Smith
    3 | Pelicula 3 |           2 |  2 | Jane Doe
 NULL | NULL    |        NULL |  5 | Bree Jensen
 NULL | NULL    |        NULL |  4 | Bev Scott
 NULL | NULL    |        NULL |  3 | Xavier Wills
(6 filas)
</code></pre><p>Nuestro conjunto de resultados ahora devuelve la fila de cada director en la tabla <code>directorios</code> y, si existe, los datos de las <code>peliculas</code>.</p><p>Todo lo que hemos hecho es cambiar qué tabla estamos considerando como la "primaria" —la tabla de la que queremos ver todos los datos, independientemente de si existen sus datos asociados.</p><h3 id="left-join-right-join-en-aplicaciones-de-producci-n"><strong><code>LEFT JOIN</code> / <code>RIGHT JOIN</code> en aplicaciones de producción</strong></h3><p>En una aplicación de producción, solo uso <code>LEFT JOIN</code> y nunca uso <code>RIGHT JOIN</code>.</p><p>Hago esto porque, en mi opinión, un <code>LEFT JOIN</code> hace que la consulta sea más fácil de leer y comprender.</p><p>Cuando escribo consultas, me gusta pensar en comenzar con un conjunto de resultados "base", digamos que todas las películas, y entonces traer o sustraer) grupos de cosas de esa base.</p><p>Debido a que me gusta comenzar con una base, el <code>LEFT JOIN</code> se ajusta a esta línea de pensamiento. Quiero todas las filas de mi tabla base (la tabla "izquierda") y condicionalmente quiero las filas de la tabla "derecha".</p><p>En la práctica, no creo haber visto nunca un <code>RIGHT JOIN</code>en una aplicación de producción. No hay nada de malo con un <code>RIGHT JOIN</code>—solo creo que hace que la consulta sea más difícil de entender.</p><h3 id="reescribiendo-right-join"><strong>Reescribiendo <code>RIGHT JOIN</code></strong></h3><p>Si quisiéramos cambiar nuestro escenario anterior y, en su lugar, devolver a todos los directorios y condicionalmente sus películas, podemos reescribir fácilmente <code>RIGHT JOIN</code> en <code>LEFT JOIN</code>.</p><p>Todo lo que tenemos que hacer es cambiar el orden de las tablas en la consulta y cambiar de <code>RIGHT</code> a <code>LEFT</code>:</p><pre><code class="language-sql">SELECT *
FROM directorios
LEFT JOIN peliculas
  ON peliculas.director_id = directorios.id;
</code></pre><blockquote><strong><strong>Not</strong>a<strong>:</strong> </strong>Me gusta poner ON en la tabla que se está uniendo (la tabla "derecha" —en el ejemplo anterior <code>peliculas</code>) primero en la condición del join (<code>ON peliculas.director_id = ...</code>)—pero esa es solo mi preferencia personal.</blockquote><h2 id="filtrado-usando-left-join"><strong>Filtrado usando <code>LEFT JOIN</code></strong></h2><p>Hay dos casos de uso para usar un <code>LEFT JOIN</code> (o<code>RIGHT JOIN</code>).</p><p>El primer caso de uso que ya lo hemos cubierto: devolver todas las filas de una tabla y condicionalmente de otra.</p><p>El segundo caso de uso es devolver filas de la primera tabla <strong>donde los datos de la segunda tabla no están presentes<strong>.</strong></strong></p><p>El escenario sería así: encontrar directorios <em>que<em> </em>no pertenezcan a una película<em>.</em></em></p><p>Para hacer esto, comenzaremos con un <code>LEFT JOIN</code> y nuestra tabla de <code>directorios</code> será la tabla primaria o la tabla "izquierda":</p><pre><code class="language-sql">SELECT *
FROM directorios
LEFT JOIN peliculas
  ON peliculas.director_id = directorios.id;
</code></pre><p>Para un director que no pertenece a una película, las columnas de la tabla <code>peliculas</code> son <code>NULL</code>:</p><pre><code> id |     nombre     |  id  |  nombre   | director_id
----+--------------+------+---------+-------------
  1 | John Smith   |    1 | Pelicula 1 |           1
  1 | John Smith   |    2 | Pelicula 2 |           1
  2 | Jane Doe     |    3 | Pelicula 3 |           2
  5 | Bree Jensen  | NULL | NULL    |        NULL
  4 | Bev Scott    | NULL | NULL    |        NULL
  3 | Xavier Wills | NULL | NULL    |        NULL
(6 filas)
</code></pre><p>En nuestro ejemplo, los ID de director 3, 4, y 5 no pertenecen a una película.</p><p>Para filtrar nuestro conjunto de resultados solo a estas filas, podemos agregar una cláusula <code>WHERE</code> &nbsp;para devolver solo las filas donde los datos de la película son <code>NULL</code>:</p><pre><code class="language-sql">SELECT *
FROM directorios
LEFT JOIN peliculas
  ON peliculas.director_id = directorios.id
WHERE peliculas.id IS NULL;
</code></pre><pre><code> id |     nombre     |  id  | nombre | director_id
----+--------------+------+------+-------------
  5 | Bree Jensen  | NULL   | NULL |        NULL
  4 | Bev Scott    | NULL   | NULL |        NULL
  3 | Xavier Wills | NULL   | NULL |        NULL
(3 filas)
</code></pre><p>¡Y allí están nuestros tres directorios sin película!</p><p>Es común usar la columna<code>id</code> de la tabla para filtrar (<code>WHERE peliculas.id IS NULL</code>), pero todas las columnas de la tabla &nbsp;<code>peliculas</code> son <code>NULL</code>—por lo que cualquiera de ellas funcionaría.</p><p>(Dado que sabemos que todas las columnas de la tabla <code>peliculas</code> serán <code>NULL</code>, en la consulta anterior podríamos escribir <code>SELECT directorios.*</code> en lugar de <code>SELECT *</code> para devolver toda la información del director.)</p><h3 id="usandoleft-join-para-encontrar-coincidencias"><strong>Usando<code>LEFT JOIN</code> para encontrar coincidencias</strong></h3><p>En nuestra consulta anterior encontramos directorios <em>que no</em> pertenecían a películas.</p><p>Usando nuestra misma estructura, podríamos encontrar directorios que <em>si </em>pertenecieran a películas cambiando nuestra condición <code>WHERE</code> &nbsp;para buscar filas donde los datos de la película <em>no sean</em> <code>NULL</code>:</p><pre><code class="language-sql">SELECT *
FROM directorios
LEFT JOIN peliculas
  ON peliculas.director_id = directorios.id
WHERE peliculas.id IS NOT NULL;
</code></pre><pre><code> id |    nombre    | id |  nombre   | director_id
----+------------+----+---------+-------------
  1 | John Smith |  1 | Pelicula 1 |           1
  1 | John Smith |  2 | Pelicula 2 |           1
  2 | Jane Doe   |  3 | Pelicula 3 |           2
(3 filas)
</code></pre><p>Esto puede parecer útil, pero en realidad acabamos de volver a implementar <code>INNER JOIN</code>!</p><h2 id="m-ltiple-joins-o-combinaciones"><strong>Múltiple joins o combinaciones</strong></h2><p>Hemos visto cómo unir dos tablas, pero ¿qué pasa con las combinaciones múltiples seguidas?</p><p>En realidad es bastante simple, pero para ilustrar esto necesitamos una tercera tabla: <code>tickets</code>.</p><p>Esta tabla representará las entradas vendidas para una película:</p><pre><code class="language-sql">CREATE TABLE tickets(
  id SERIAL PRIMARY KEY,
  movie_id INTEGER REFERENCES peliculas NOT NULL
);

INSERT INTO tickets(pelicula_id) VALUES (1), (1), (3);
</code></pre><p>La tabla <code>tickets</code> solo tiene un <code>id</code> y una referencia a la película: <code>pelicula_id</code>.</p><p>También hemos insertado dos boletos vendidos para la película ID 1, y un boleto vendido para la película ID 3.</p><p>¡Ahora, unamos los<code>directorios</code> a las <code>peliculas</code>—y luego <code>peliculas</code> a <code>tickets</code>!</p><pre><code class="language-sql">SELECT *
FROM directorios
INNER JOIN peliculas
  ON peliculas.director_id = directors.id
INNER JOIN tickets
  ON tickets.pelicula_id = peliculas.id;
</code></pre><p>Dado que se trata de inner joins, el orden en que escribimos las combinaciones no importa. Podríamos haber comenzado con los <code>tickets</code>, luego combinar a las <code>peliculas</code>, y luego combinar a los <code>directorios</code>.</p><p>De nuevo, todo se reduce a lo que se está tratando de consultar y lo que hace que la consulta sea más comprensible.</p><p>En nuestro conjunto de resultados, notaremos que hemos reducido aún más las filas que se devuelven:</p><pre><code> id |    nombre    | id |  nombre   | director_id | id | pelicula_id
----+------------+----+---------+-------------+----+----------
  1 | John Smith |  1 | Pelicula 1 |           1 |  1 |        1
  1 | John Smith |  1 | Pelicula 1 |           1 |  2 |        1
  2 | Jane Doe   |  3 | Pelicula 3 |           2 |  3 |        3
(3 filas)
</code></pre><p>Esto tiene sentido porque hemos agregado otro <code>INNER JOIN</code>. En efecto, esto agrega otra condición <em><em>"AND"</em></em>a nuestra consulta.</p><p>Nuestra consulta esencialmente dice: <em><em>"</em>devuelve<em> </em>todos los<em> director</em>io<em>s</em> que pertenezcan a </em>películas<em> <em> </em><strong>pero que también tienen</strong><em> </em>tickets vendidos<em>."</em></em></p><p>Si, en cambio, quisiéramos encontrar directorios que pertenezcan a películas <em>que no hayan vendido tickest todavía</em>, podríamos sustituir nuestro último <code>INNER JOIN</code> por un <code>LEFT JOIN</code>:</p><pre><code class="language-sql">SELECT *
FROM directorios
JOIN peliculas
  ON peliculas.director_id = directorios.id
LEFT JOIN tickets
  ON tickets.pelicula_id = peliculas.id;
</code></pre><p>Podemos ver que la <code>Pelicula 2</code> hora está de vuelta en el conjunto de resultados:</p><pre><code> id |    nombre    | id |  nombre   | director_id |  id  | pelicula_id
----+------------+----+---------+-------------+------+----------
  1 | John Smith |  1 | Pelicula 1 |           1 |    1 |        1
  1 | John Smith |  1 | Pelicula 1 |           1 |    2 |        1
  2 | Jane Doe   |  3 | Pelicula 3 |           2 |    3 |        3
  1 | John Smith |  2 | Pelicula 2 |           1 | NULL |     NULL
(4 filas)
</code></pre><p>Esta película no tuvo ninguna venta de boletos, por lo que anteriormente se excluyó del conjunto de resultados debido a <code>INNER JOIN</code>.</p><p>Dejaré esto como <em><em>E</em>j<em>e</em>rcicio<em> </em>para el lector<em> ™</em></em>, pero ¿cómo encontraría directorios que pertenezcan a películas que <strong>no</strong> tienen venta de boletos?</p><h3 id="orden-de-ejecuci-n-de-la-combinaci-n"><strong>Orden de ejecución de la combinación</strong></h3><p>Al final, realmente no nos importa en qué orden se ejecutan las combinaciones.</p><p>Una de las diferencias clave entre SQL y otros lenguajes de programación modernos es que SQL es un lenguaje <strong>declarativo</strong>.</p><p>Esto significa que especificamos el resultado que queremos, pero no especificamos los detalles de ejecución; esos detalles se dejan al planificador de consultas de la base de datos. Especificamos las combinaciones que queremos y las condiciones en ellas y el planificador de consultas se encarga del resto.</p><p>Pero, en realidad, la base de datos no une tres tablas al mismo tiempo. En su lugar, probablemente unirá las dos primeras tablas en un resultado intermedio y luego unirá ese conjunto de resultados intermedios a la tercera tabla.</p><p>(<strong><strong>Not</strong>a<strong>: </strong></strong>Esta es una explicación algo simplificada.)</p><p>Entonces, como estamos trabajando con múltiples joins en las consultas, podemos pensar en ellas como una serie de joins entre dos tablas, aunque una de esas tablas puede llegar a ser bastante grande.</p><h2 id="joins-con-condiciones-extra"><strong>Joins con condiciones extra</strong></h2><p>El último tema que cubriremos es un join con condiciones adicionales.</p><p>Similar a una cláusula <code>WHERE</code>, podemos agregar tantas condiciones como queramos a nuestras condiciones de join.</p><p>Por ejemplo, si quisiéramos encontrar películas con directorios <em>que no se llamen</em> <em><em>"John Smith"</em></em>, podríamos agregar esa condición extra a nuestra join con un <code>AND</code>:</p><pre><code class="language-sql">SELECT *
FROM peliculas
INNER JOIN directorios
  ON directors.id = peliculas.director_id
  AND directorios.name &lt;&gt; 'John Smith'</code></pre><p>Podemos usar cualquier operador que pondríamos en una cláusula <code>WHERE</code>en esta condición de join.</p><p>También obtenemos el mismo resultado de esta consulta si colocamos la condición en una cláusula <code>WHERE</code> en su lugar:</p><pre><code class="language-sql">SELECT *
FROM peliculas
INNER JOIN directorios
  ON directorios.id = peliculas.director_id
WHERE directorios.name &lt;&gt; 'John Smith';</code></pre><p>Hay algunas diferencias sutiles que ocurren bajo el capó aquí, pero para el propósito de este artículo, el conjunto de resultados es el mismo.</p><p>(Si no está familiarizado con todas las formas en que puede filtrar una consulta SQL, consulte el artículo mencionado anteriormente aquí.)</p><h2 id="la-realidad-acerca-de-escribir-consultas-con-joins"><strong>La realidad acerca de escribir consultas con joins</strong></h2><p>En realidad, solo uso combinaciones de tres maneras diferentes:</p><h4 id="inner-join-1"><strong><code>INNER JOIN</code></strong></h4><p>El primer caso de uso son los registros donde <strong>existe</strong> la relación entre dos tablas. Esto lo cumple el <code>INNER JOIN</code>.</p><p>Estas son situaciones como encontrar "<em>películas que tienen directorios<em>"</em></em> o <em><em>"</em>usuarios con publicaciones<em>".</em></em></p><h4 id="left-join"><strong><code>LEFT JOIN</code></strong></h4><p>El segundo caso de uso son los registros de una tabla —y si existe la relación—los registros de una segunda tabla. Esto lo cumple el <code>LEFT JOIN</code>.</p><p>Estas son situaciones como encontrar <em><em>"</em>películas con directorios si es que tienen uno<em>"</em></em> o <em><em>"</em></em>usuarios con publicaciones si tienen alguna<em><em>."</em></em></p><h4 id="left-join-exclusi-n"><strong><code>LEFT JOIN</code> exclusión</strong></h4><p>El tercer caso de uso más común es nuestro segundo caso de uso para un <code>LEFT JOIN</code>: encontrar registros en una tabla que<em><em> </em></em><strong>no</strong><em><em> </em></em>tienen una relación en la segunda tabla.</p><p>Estas son situaciones como <em><em>"</em>películas sin directorios<em>"</em></em> o <em><em>"</em>usuarios sin publicaciones<em>."</em></em></p><h3 id="dos-tipos-de-combinaciones-o-joins-muy-tiles"><strong>Dos tipos de combinaciones o joins muy útiles</strong></h3><p>Creo que nunca he usado un <code>FULL OUTER JOIN</code> o un <code>RIGHT JOIN</code> en una aplicación de producción. El caso de uso simplemente no aparece con la frecuencia suficiente o la consulta se puede escribir de una manera más clara (en el caso de <code>RIGHT JOIN</code>).</p><p>Ocasionalmente, he usado un <code>CROSS JOIN</code> para cosas como distribuir registros en un rango de fechas (como lo miramos al principio), pero ese escenario tampoco aparece con demasiada frecuencia.</p><p>Entonces, ¡buenas noticias! En realidad, solo hay dos tipos de combinaciones que debe comprender para el 99,9 % de los casos de uso que encontraras: <code>INNER JOIN</code> y <code>LEFT JOIN</code>!</p><p>Si te gustó este artículo, me puedes seguir en <a href="https://twitter.com/johnmosesman">Twitter </a>donde hablo de base de datos y temas relacionados con el desarrollo.</p><p>¡Gracias por leer!</p><p>John</p><p><strong><strong>P.S.</strong></strong> un consejo adicional por haber leido hasta el final: la mayoría de los sistemas de base de datos te permitiran escribir simplemente <code>JOIN</code> en lugar de<code>INNER JOIN</code>—lo que te ahorrará un poco de tipeo adicional. :)</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
