sql >> Base de Datos >  >> RDS >> PostgreSQL

Uso de uniones para combinar datos de diferentes tablas en PostgreSQL


Introducción

Dividir datos relacionados en tablas separadas puede ser beneficioso desde el punto de vista de la coherencia, la flexibilidad y ciertos tipos de rendimiento. Sin embargo, aún necesita una forma razonable de reintegrar registros cuando la información relevante abarca varias tablas.

En bases de datos relacionales, se une ofrecen una forma de combinar los registros en dos o más tablas en función de valores de campo comunes. Diferentes tipos de uniones pueden lograr diferentes resultados dependiendo de cómo se deben manejar las filas no coincidentes. En esta guía, analizaremos los diversos tipos de combinaciones que ofrece PostgreSQL y cómo puede usarlas para combinar datos de tablas de múltiples fuentes.



¿Qué son las combinaciones?

En resumen, unirse son una forma de mostrar datos de varias tablas. Lo hacen uniendo registros de diferentes fuentes en función de los valores coincidentes en ciertas columnas. Cada fila resultante consta de un registro de la primera tabla combinado con una fila de la segunda tabla, según una o más columnas de cada tabla que tengan el mismo valor.

La sintaxis básica de una combinación se ve así:

SELECT    *FROM    <first_table><join_type> <second_table>    <join_condition>;

En una combinación, cada fila resultante se construye incluyendo todas las columnas de la primera tabla seguidas de todas las columnas de la segunda tabla. El SELECT parte de la consulta se puede utilizar para especificar las columnas exactas que desea mostrar.

Se pueden construir varias filas a partir de las tablas originales si los valores de las columnas utilizadas para la comparación no son únicos. Por ejemplo, imagine que tiene una columna que se compara desde la primera tabla que tiene dos registros con un valor de "rojo". Coincide con esto una columna de la segunda tabla que tiene tres filas con ese valor. La combinación producirá seis filas diferentes para ese valor que representan las diversas combinaciones que se pueden lograr.

El tipo de combinación y las condiciones de combinación determinan cómo se construye cada fila que se muestra. Esto afecta lo que sucede con las filas de cada tabla que no tener una coincidencia en la condición de unión.

Por conveniencia, muchas uniones hacen coincidir la clave principal en una tabla con una clave externa asociada en la segunda tabla. Aunque el sistema de la base de datos solo utiliza las claves principal y externa para mantener las garantías de consistencia, su relación a menudo las convierte en buenas candidatas para las condiciones de combinación.



Diferentes tipos de combinaciones

Hay varios tipos de combinaciones disponibles, cada una de las cuales producirá potencialmente resultados diferentes. Comprender cómo se construye cada tipo lo ayudará a determinar cuál es apropiado para diferentes escenarios.


Inner join

La unión predeterminada se llama unión interna . En PostgreSQL, esto se puede especificar usando INNER JOIN o simplemente JOIN .

Aquí hay un ejemplo típico que demuestra la sintaxis de una unión interna:

SELECT    *FROM    table_1[INNER] JOIN table_2    ON table_1.id = table_2.table_1_id;

Una combinación interna es el tipo de combinación más restrictivo porque solo muestra filas creadas al combinar filas de cada tabla. Las filas de las tablas constituyentes que no tenían una contrapartida coincidente en la otra tabla se eliminan de los resultados. Por ejemplo, si la primera tabla tiene un valor de "azul" en la columna de comparación y la segunda tabla no tiene ningún registro con ese valor, esa fila se suprimirá de la salida.

Si representa los resultados como un diagrama de Venn de las tablas de componentes, una unión interna le permite representar el área superpuesta de los dos círculos. No se muestra ninguno de los valores que solo existían en una de las tablas.



Unión izquierda

Una combinación izquierda es una combinación que muestra todos los registros encontrados en una combinación interna, además de todos los no coincidentes filas de la primera tabla. En PostgreSQL, esto se puede especificar como LEFT OUTER JOIN o simplemente como LEFT JOIN .

La sintaxis básica de una combinación izquierda sigue este patrón:

SELECT    *FROM    table_1LEFT JOIN table_2    ON table_1.id = table_2.table_1_id;

Una combinación izquierda se construye realizando primero una combinación interna para construir filas a partir de todos los registros coincidentes en ambas tablas. Posteriormente, también se incluyen los registros no coincidentes de la primera tabla. Dado que cada fila en una combinación incluye las columnas de ambas tablas, las columnas no coincidentes usan NULL como el valor de todas las columnas de la segunda tabla.

Si representa los resultados como un diagrama de Venn de las tablas de componentes, una combinación izquierda le permite representar todo el círculo izquierdo. Las partes del círculo de la izquierda representadas por la intersección entre los dos círculos tendrán datos adicionales complementados por la tabla de la derecha.



Unión derecha

Una combinación derecha es una combinación que muestra todos los registros encontrados en una combinación interna, además de todos los no coincidentes filas de la segunda tabla. En PostgreSQL, esto se puede especificar como RIGHT OUTER JOIN o simplemente como RIGHT JOIN .

La sintaxis básica de una combinación derecha sigue este patrón:

SELECT    *FROM    table_1RIGHT JOIN table_2    ON table_1.id = table_2.table_1_id;

Una combinación derecha se construye realizando primero una combinación interna para construir filas a partir de todos los registros coincidentes en ambas tablas. Posteriormente, también se incluyen los registros no coincidentes de la segunda tabla. Dado que cada fila en una combinación incluye las columnas de ambas tablas, las columnas no coincidentes usan NULL como el valor de todas las columnas de la primera tabla.

Si representa los resultados como un diagrama de Venn de las tablas de componentes, una unión a la derecha le permite representar todo el círculo a la derecha. Las partes del círculo de la derecha representadas por la intersección entre los dos círculos tendrán datos adicionales complementados por la tabla de la izquierda.



Unión completa

Una combinación completa es una combinación que muestra todos los registros encontrados en una combinación interna, además de todos los no coincidentes filas de ambas tablas de componentes. En PostgreSQL, esto se puede especificar como FULL OUTER JOIN o simplemente como FULL JOIN .

La sintaxis básica de una combinación completa sigue este patrón:

SELECT    *FROM    table_1FULL JOIN table_2    ON table_1.id = table_2.table_1_id;

Una combinación completa se construye realizando primero una combinación interna para construir filas a partir de todos los registros coincidentes en ambas tablas. Posteriormente, también se incluyen los registros no coincidentes de ambas tablas. Dado que cada fila en una combinación incluye las columnas de ambas tablas, las columnas no coincidentes usan NULL como el valor de todas las columnas en la otra tabla no coincidente.

Si representa los resultados como un diagrama de Venn de las tablas de componentes, una combinación completa le permite representar ambos círculos de componentes por completo. La intersección de los dos círculos tendrá valores proporcionados por cada una de las tablas de componentes. Las partes de los círculos fuera del área superpuesta tendrán los valores de la tabla a la que pertenecen, usando NULL para completar las columnas que se encuentran en la otra tabla.



Unión cruzada

Una unión especial llamada CROSS JOIN también está disponible. Una combinación cruzada no utiliza ninguna comparación para determinar si las filas de cada tabla coinciden entre sí. En cambio, los resultados se construyen simplemente agregando cada una de las filas de la primera tabla a cada una de las filas de la segunda tabla.

Esto produce un producto cartesiano de las filas en dos o más tablas. En efecto, este estilo de combinación combina filas de cada tabla incondicionalmente. Entonces, si cada tabla tiene tres filas, la tabla resultante tendrá nueve filas que contienen todas las columnas de ambas tablas.

Por ejemplo, si tiene una tabla llamada t1 combinado con una tabla llamada t2 , cada uno con filas r1 , r2 y r3 , el resultado serían nueve filas combinadas así:

t1.r1 + t2.r1t1.r1 + t2.r2t1.r1 + t2.r3t1.r2 + t2.r1t1.r2 + t2.r2t1.r2 + t2.r3t1.r3 + t2.r1t1.r3 + t2.r2t1.r3 + t2.r3


Auto-unión

Una autocombinación es cualquier combinación que combina las filas de una tabla consigo misma. Puede que no sea inmediatamente evidente cómo esto podría ser útil, pero en realidad tiene muchas aplicaciones comunes.

A menudo, las tablas describen entidades que pueden cumplir múltiples roles en relación entre sí. Por ejemplo, si tiene una tabla de people , cada fila podría contener potencialmente una mother columna que hace referencia a otras people en la mesa. Una unión automática le permitiría unir estas filas diferentes uniendo una segunda instancia de la tabla a la primera donde estos valores coinciden.

Dado que self une la referencia a la misma tabla dos veces, se requieren alias de tabla para eliminar la ambigüedad de las referencias. En el ejemplo anterior, por ejemplo, podría unir las dos instancias de people tabla usando los alias people AS children y people AS mothers . De esa forma, puede especificar a qué instancia de la tabla se refiere al definir las condiciones de combinación.

Aquí hay otro ejemplo, esta vez representando relaciones entre empleados y gerentes:

SELECT    *FROM    people AS employeeJOIN people AS manager    ON employee.manager_id = manager.id;



Condiciones de unión

Al combinar tablas, la condición de unión determina cómo se unirán las filas para formar los resultados compuestos. La premisa básica es definir las columnas de cada tabla que deben coincidir para que se produzca la unión en esa fila.


El ON cláusula

La forma más estándar de definir las condiciones para las uniones de tablas es con ON cláusula. El ON La cláusula usa un signo igual para especificar las columnas exactas de cada tabla que se compararán para determinar cuándo puede ocurrir una combinación. PostgreSQL utiliza las columnas proporcionadas para unir las filas de cada tabla.

El ON La cláusula es la más detallada, pero también la más flexible de las condiciones de combinación disponibles. Permite la especificidad independientemente de cuán estandarizados estén los nombres de las columnas de cada tabla que se combine.

La sintaxis básica de ON cláusula se ve así:

SELECT    *FROM    table1JOIN    table2ON    table1.id = table2.ident;

Aquí, las filas de table1 y table2 se unirá siempre que el id columna de table1 coincide con el ident columna de table2 . Debido a que se utiliza una unión interna, los resultados solo mostrarán las filas que se unieron. Dado que la consulta utiliza el comodín * carácter, se mostrarán todas las columnas de ambas tablas.

Esto significa que tanto el id columna de table1 y el ident columna de table2 se mostrarán, aunque tengan el mismo valor exacto en virtud de satisfacer la condición de unión. Puede evitar esta duplicación llamando a las columnas exactas que desea mostrar en SELECT lista de columnas.



El USING cláusula

El USING cláusula es una abreviatura para especificar las condiciones de un ON cláusula que se puede utilizar cuando las columnas que se comparan tienen el mismo nombre en ambas tablas. El USING La cláusula toma una lista, entre paréntesis, de los nombres de columnas compartidas que deben compararse.

La sintaxis general del USING cláusula usa este formato:

SELECT    *FROM    table1JOIN    table2USING    (id, state);

Esta combinación combina table1 con table2 cuando dos columnas que comparten ambas tablas (id y state ) tienen valores coincidentes.

Esta misma unión podría expresarse de manera más detallada usando ON así:

SELECT    *FROM    table1JOIN    table2ON    table1.id = table2.id AND table1.state = table2.state;

Si bien las dos uniones anteriores darían como resultado la construcción de las mismas filas con los mismos datos presentes, se mostrarían ligeramente diferentes. Mientras el ON cláusula incluye todas las columnas de ambas tablas, el USING cláusula suprime las columnas duplicadas. Entonces, en lugar de que haya dos id separados columnas y dos state separados columnas (una para cada tabla), los resultados solo tendrían una de cada una de las columnas compartidas, seguida de todas las demás columnas proporcionadas por table1 y table2 .



La NATURAL cláusula

El NATURAL cláusula es otra forma abreviada que puede reducir aún más la verbosidad del USING cláusula. UN NATURAL join no especifica ninguna columnas a emparejar. En su lugar, PostgreSQL unirá automáticamente las tablas en función de todas las columnas que tengan columnas coincidentes en cada base de datos.

La sintaxis general del NATURAL la cláusula de unión se ve así:

SELECT    *FROM    table1NATURAL JOIN    table2;

Suponiendo que table1 y table2 ambos tienen columnas llamadas id , state y company , la consulta anterior sería equivalente a esta consulta utilizando ON cláusula:

SELECT    *FROM    table1JOIN    table2ON    table1.id = table2.id AND table1.state = table2.state AND table1.company = table2.company;

Y esta consulta usando USING cláusula:

SELECT    *FROM    table1JOIN    table2USING    (id, state, company);

Como el USING cláusula, el NATURAL La cláusula suprime las columnas duplicadas, por lo que solo habría una sola instancia de cada una de las columnas unidas en los resultados.

Mientras que el NATURAL cláusula puede reducir la verbosidad de sus consultas, se debe tener cuidado al usarla. Debido a que las columnas utilizadas para unir las tablas se calculan automáticamente, si las columnas de las tablas de componentes cambian, los resultados pueden ser muy diferentes debido a las nuevas condiciones de unión.




Condiciones de unión y WHERE cláusula

Las condiciones de unión comparten muchas características con las comparaciones utilizadas para filtrar filas de datos usando WHERE cláusulas. Ambas construcciones definen expresiones que deben evaluarse como verdaderas para que se considere la fila. Debido a esto, no siempre es intuitivo cuál es la diferencia entre incluir comparaciones adicionales en un WHERE construir versus definirlos dentro de la propia cláusula de unión.

Para comprender las diferencias que resultarán, debemos observar el orden en que PostgreSQL procesa las diferentes partes de una consulta. En este caso, los predicados en la condición de combinación se procesan primero para construir la tabla virtual combinada en la memoria. Después de esta etapa, las expresiones dentro de WHERE se evalúan para filtrar las filas resultantes.

Como ejemplo, supongamos que tenemos dos tablas llamadas customer y order que tenemos que unirnos. Queremos unir las dos tablas haciendo coincidir el customer.id columna con el order.customer_id columna. Además, estamos interesados ​​en las filas en el order tabla que tiene un product_id de 12345.

Teniendo en cuenta los requisitos anteriores, tenemos dos condiciones que nos importan. Sin embargo, la forma en que expresamos estas condiciones determinará los resultados que recibamos.

Primero, usemos ambos como condiciones de unión para un LEFT JOIN :

SELECT    customer.id AS customer_id,    customer.name,    order.id AS order_id,    order.product_idFROM    customerLEFT JOIN    orderON    customer.id = order.customer_id AND order.product_id = 12345;

Los resultados podrían verse así:

 customer_id |   name   | order_id | product_id ------------+----------+----------+------------        4380 | Acme Co  |      480 |      12345        4380 | Acme Co  |      182 |      12345         320 | Other Co |      680 |      12345        4380 | Acme Co  |          |         320 | Other Co |          |          20 | Early Co |          |        8033 | Big Co   |          |(7 rows)

PostgreSQL llegó a este resultado realizando las siguientes operaciones:

  1. Combina cualquier fila en el customer tabla con el order tabla donde:
    • customer.id coincide con order.customer_id .
    • order.product_id coincide con 12345
  2. Debido a que estamos usando una combinación izquierda, incluya cualquier no coincidente filas de la tabla de la izquierda (customer ), rellenando las columnas de la tabla de la derecha (order ) con NULL valores.
  3. Mostrar solo las columnas enumeradas en SELECT especificación de columna.

El resultado es que todas nuestras filas unidas coinciden con las dos condiciones que buscamos. Sin embargo, la combinación izquierda hace que PostgreSQL también incluya filas de la primera tabla que no cumplieron con la condición de combinación. Esto da como resultado filas "sobrantes" que no parecen seguir la intención aparente de la consulta.

Si movemos la segunda consulta (order.product_id =12345) a un WHERE cláusula, en lugar de incluirla como una condición de unión, obtenemos resultados diferentes:

SELECT    customer.id AS customer_id,    customer.name,    order.id AS order_id,    order.product_idFROM    customerLEFT JOIN    orderON    customer.id = order.customer_idWHERE    order.product_id = 12345;

Esta vez, solo se muestran tres filas:

 customer_id |   name   | order_id | product_id ------------+----------+----------+------------        4380 | Acme Co  |      480 |      12345        4380 | Acme Co  |      182 |      12345         320 | Other Co |      680 |      12345(3 rows)

El orden en que se ejecutan las comparaciones es la razón de estas diferencias. Esta vez, PostgreSQL procesa la consulta de esta manera:

  1. Combina cualquier fila en el customer tabla con el order tabla donde customer.id coincide con order.customer_id .
  2. Debido a que estamos usando una combinación izquierda, incluya cualquier no coincidente filas de la tabla de la izquierda (customer ), rellenando las columnas de la tabla de la derecha (order ) con NULL valores.
  3. Evaluar el WHERE cláusula para eliminar cualquier fila que no tenga 12345 como valor para order.product_id columna.
  4. Mostrar solo las columnas enumeradas en SELECT especificación de columna.

Esta vez, a pesar de que estamos usando una combinación izquierda, WHERE La cláusula trunca los resultados al filtrar todas las filas sin el product_id correcto . Porque cualquier fila no coincidente tendría product_id establecido en NULL , esto elimina todas las filas no coincidentes que se completaron con la combinación izquierda. También elimina cualquiera de las filas que coincidieron con la condición de combinación que no pasó esta segunda ronda de comprobaciones.

Comprender el proceso básico que utiliza PostgreSQL para ejecutar sus consultas puede ayudarlo a evitar algunos errores fáciles de cometer pero difíciles de depurar mientras trabaja con sus datos.



Conclusión

En esta guía, cubrimos cómo las uniones permiten que las bases de datos relacionales combinen datos de diferentes tablas para proporcionar respuestas más valiosas. Hablamos sobre las diversas uniones que admite PostgreSQL, la forma en que cada tipo ensambla sus resultados y qué esperar al usar tipos específicos de uniones. Luego, repasamos diferentes formas de definir las condiciones de unión y observamos cómo la interacción entre las uniones y WHERE cláusula puede dar lugar a sorpresas.

Las uniones son una parte esencial de lo que hace que las bases de datos relacionales sean lo suficientemente poderosas y flexibles para manejar tantos tipos diferentes de consultas. Organizar los datos utilizando límites lógicos y al mismo tiempo poder recombinar los datos de formas novedosas caso por caso brinda a las bases de datos relacionales como PostgreSQL una versatilidad increíble. Aprender a realizar esta unión entre tablas le permitirá crear consultas más complejas y confiar en la base de datos para crear imágenes completas de sus datos.