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:
- Combina cualquier fila en el
customer
tabla con elorder
tabla donde:customer.id
coincide conorder.customer_id
.order.product_id
coincide con 12345
- 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
) conNULL
valores. - 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:
- Combina cualquier fila en el
customer
tabla con elorder
tabla dondecustomer.id
coincide conorder.customer_id
. - 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
) conNULL
valores. - Evaluar el
WHERE
cláusula para eliminar cualquier fila que no tenga 12345 como valor paraorder.product_id
columna. - 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.