SQL Joins explicados de forma gráfica con diagramas Venn

14
84189

SQL Joins explicados de forma gráfica con diagramas Venn

SQL92 Joins, INNER JOIN, FULL OUTER JOIN, LEFT OUTER JOIN como nunca los habías visto.

 

Objetivo del documento:
Presentar de forma fácil y clara el ámbito de registros dada una entidad que cubren cada una de las sentencias JOIN del SQL92.

Fecha de publicación 02/09/2010

Lecturas recomendadas:

http://www.w3schools.com/sql

Una simple ayuda

El lenguaje SQL es aveces el gran olvidado por los desarrolladores, cada vez abundan mas los frameworks que abstraen al desarrollador del contacto con el modelo de negocio.

He escrito este documento, basándome en otros similares para ayudar a entender con un diagrama de Vann, los diferentes tipos de Join’s que SQL92 soporta.

Existen tecnologías que abstraen completamente del modelo de negocio, para el desarrollador funcionan creando una serie de clases de Dominio que define el modelo, sin importar qué base de datos o de qué fabricante sea esta. Por ejemplo Ruby on Rails, GRails, … usando un conjunto de tecnologías, como Hibernate configuradas por convención dentro del propio framework.

También es muy extendido el uso de aplicaciones que permiten modelar el negocio de forma gráfica, ERM (como DBSchema), y normalmente después se usa un ORM’s que les hacen el trabajo sucio de forma elegante y segura.

Todo vale, pero la realidad de las empresas TIC es que necesitan profesionales serios y conscientes que entiendan y controlen todas las capas para que un sistema funciona como se espera y está diseñado, y no se deje nada al azar.

El desarrollador, muy frecuentemente recurre a activar trazas o aplicaciones de monitorización de actividad que nos desvelen, qué está haciendo nuestro framework con nuestro modelo de negocio. Existen aplicaciones que esnifan directamente de la base de datos esta información para que podamos analizarla, el obsoleto Profile y Analyzer que incluía Microsoft SQL Server es un ejemplo de ellos.

Finalmente cuando tenemos delante la query sucede que hace tanto tiempo que no trabajamos con SQL que no entendemos qué hace exactamente, sobre todo si está trabajando con tablas relacionadas y nos encontramos con una consulta que afecta a varias entidades.

Espero que este documento ayude a reducir el tiempo invertido a descubrir porqué se comporta una SQL de un modo u otro.

Convenciones

Este documento asume que siempre que la «TABLA A» esta a la izquierda y la «TABLA B» a la derecha de las sentencias.

Para los ejemplos vamos a utilizar 2 tablas que van a contener los siguientes datos:

id name | id name
1 Roberto | 1 Alex
2 Juan | 2 Carlos
3 Rubén | 3 Juan
4 Carlos | 4 Saúl

INNER JOIN

SELECT * FROM TableA INNER JOIN TableB ON TableA.name = TableB.name

id name | id name
2 Juan | 2 Carlos
4 Carlos | 3 Juan

El resultado son solo el conjunto de registros que coinciden en ambas tablas.Inner Join

FULL OUTER JOIN

SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name

id name | id name
1 Roberto | null null
2 Juan | 3 Juan
3 Rubén | null null
4 Carlos | 2 Carlos
null null | 1 Alex
null null | 4 Saúl

El resultado es el conjunto total de registros de ambas tablas, coincidiendo aquellos registros cuando sea posible. Si no hay conicidencias, se asignan nulos.

Full Outer Join

FULL OUTER JOIN WHERE

SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name WHERE TableA.id IS null OR TableB.id IS null

id name | id name
1 Roberto | null null
3 Rubén | null null
null null | 1 Alex
null null | 4 Saúl

El resultado es un conjunto de records únicos en la TablaA y en la TablaB, hacemos el Full Outer Join y excluimos los registros que no queremos con el Where

Full Outer Join con Where

LEFT OUTER JOIN

SELECT * FROM TableA LEFT OUTER JOIN TableB ON TableA.name = TableB.name

id name | id name
1 Roberto | null null
2 Juan | 3 Juan
3 Rubén | null null
4 Carlos | 2 Carlos

El resultado son todos los registros de la TablaA, y si es posible las coincidencias de la TablaB. Si no hay coincidencias, el lado derecho mostrará nulos.

Left Outer Join

LEFT OUTER JOIN WHERE

SELECT * FROM TableA LEFT OUTER JOIN TableB ON TableA.name = TableB.name WHERE TableB.id IS null

id name | id name
1 Roberto | null null
3 Rubén | null null

El resultado es un conjunto de registros que solo están en la TablaA, no en la TablaB. Hacemos lo mismo que en un Left Outer Join, pero eliminamos los registros que no queremos de la TablaB con el Where

Left Outer Join con Where

CROSS JOIN

Existe también la posibilidad de cruzar todos los registros con todos (producto cartesiano), imposible de dibujar con un diagramas Venn

SELECT * FROM TableA CROSS JOIN TableB

Imaginarse el resultado de todos los registros por todos es muy fácil, si tenemos 4 registros en cada tabla 4 x 4 = 16.

Cross Join

Ojo al hacer esto en tablas con muchos registros!

14 Comentarios

  1. Está muy bien explicado, lo que nos da un dibujito en información equivale a 1000 palabras… si es que la mente busca cosas simples y entiende cosas simples.

    Me aplico el cuento y muchas gracias porque además trata un concepto técnico muy interesante.

    Saludos,

  2. Hola! que tal.
    Antes que todo, agradecerte el tiempo que inviertes para hacer estos tutoriales. Y bueno para comentarte que según yo, en el resultado que muestras en el primer ejemplo (inner join), aparece de manera errónea la intersección
    id name | id name
    2 Juan | 2 Carlos
    4 Carlos | 3 Juan

    debiera ser:

    id name | id name
    2 Juan | 3 Juan
    4 Carlos | 2 Carlos.

    Saludos cordiales

  3. Genial Man !!!

    Sobretodo me gusto mucho la explicación el final de cada ejemplo : «el resultado es este y aquel «……

    Realmente simple , sencillo y sobretodo muy fácil de comprender.

    web para mis favoritos ….

    Saludos y gracias por compartir.

  4. Hola, muchas gracias por la excelente explicación.
    Una ayuda con este caso, claro si es que es posible, pues tiene varios años la publicación.
    Tengo dos tablas, estas contienen información de detalle, es decir la columna que relaciona los valores son repetibles (columna Folio), este es el caso:

    T1 | T2
    Folio Producto Cantidad-Vendida Folio Producto Cantidad-Enviar
    1 A 10 1 A 10
    1 B 10 1 B 10
    1 B 10 1 B 10 (fila que se repite es normal)
    1 C 10 1 C 10

    – Al combinar Inner Join T1.Folio = T2.Folio, T1 x T2 = 16 Filas, Producto Cartesiano

    – Si se aplica el Where T1.Producto = T2.Producto = 6 Filas (Fila Producto B aparece 4 veces, está ok, por la combinación que se realiza)

    – Si al Inicio del Select se indica DISTINTIC, aplicando el Where T1.Producto = T2.Producto = 3 Filas (Elimina del resultado el Segundo Producto B, está ok, por porqué se repite el Producto B)

    – La pregunta es ¿Es posible obtener el conjunto de resultados tal como se aprecia en el ejemplo?, esto es, que aparezca uno a uno los registros de ambas tablas, teniendo en consideración que ambas tablas siempre alojan el mismo número de registros por cada Folio con mismos productos, lo único que puede cambiar son las Cantidades.

    Posiblemente me lié con algo tan simple, a decir verdad tengo 3 días, repasando notas y notas, igual llegué a pensar que mis conocimientos ni a básicos llegan, jeje, en fin llegué al límite, igual algo tan simple no lo alcanzo a ver o entender.

    Lo único que aislaría el problema es no permitir en la captura de la venta se repitan los productos (desde luego, dentro de la misma Nota de Venta).

    Muchísimas gracias por la atención a la lectura, posibles aportes y sugerencias.

  5. Buen día…! Por aquí la solución al caso plantee en el post anterior.

    SELECT
    T.Id_VENTAS,

    T.FOLIO_VENTAS, T.CONCEPTO_VENTAS, T.CANTIDAD_VENTAS

    T.FOLIO_ENVIOS, T.CONCEPTO_ENVIOS, T.CANTIDAD_ENVIOS

    FROM
    (
    SELECT DISTINCT

    VENTAS_DETALLE.Id AS Id_VENTAS,

    VENTAS_DETALLE.FOLIO_VENTAS,
    VENTAS_DETALLE.CONCEPTO_VENTAS,
    VENTAS_DETALLE.CANTIDAD_VENTAS,

    ENVIOS_DETALLE.FOLIO_ENVIOS,
    ENVIOS_DETALLE.CONCEPTO_ENVIOS,
    ENVIOS_DETALLE.CANTIDAD_ENVIOS

    FROM

    VENTAS_DETALLE.CONCEPTO

    INNER JOIN

    ENVIOS_DETALLE.CONCEPTO

    ON VENTAS_DETALLE.FOLIO_VENTAS = ENVIOS_DETALLE.FOLIO_ENVIOS

    ) AS T

    WHERE

    T.FOLIO_VENTAS = 13643

    AND

    T.FOLIO_ENVIOS = 22

    Como se incluye el Predicado DISTINCT (Que elimina Registros duplicados) la Columna
    T.Id_VENTAS es un valor incremental el cual al tener
    T.CONCEPTO_VENTAS y T.CONCEPTO_ENVIOS en más de un registro el mismo valor,
    lo que los hace distintos es T.Id_VENTAS.

    Uhhh adiviné, era algo muy simple que no lograba distinguir.

    Saludos.

  6. Ok, asi funciona perfectamente, pero que pasa cuando tienes la misma situacion de no querer repetir registros de la tabla Detalle , pero tienes 5 joins ? ahi ya no funciona el Distinct, que otra solucion recomiendan?

  7. y que pasara si las dos tablas no tienen Primary key ya que la la migracion de datos fue de dos tablas una que es el detalle y la otra la cabecera, sin embargo la tabla detalle necesitar cargar campos de la tabla cabecera, en excel es suficiente un buscarV pero en sql como? si no hay id Unicos para cada tabla que los identifiquen…

  8. Si tengo lo siguiente:

    SELECT *
    FROM tabla_a LEFT OUTER JOIN tabla_b ON tabla_b.id = tabla_a.id

    Es lo mismo que hacer esto:

    SELECT *
    FROM tabla_b RIGHT OUTER JOIN tabla_a ON tabla_a.id = tabla_b.id

Dejar respuesta

Please enter your comment!
Please enter your name here