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

Creación de una consulta que devuelve la identificación si la condición coincide en filas de dos tablas

He leído su pregunta en Meta sobre esta pregunta en particular, permítanme explicar por qué las tres respuestas son correctas, al igual que la forma en que las resolvieron.

He incluido ejemplos de las tres respuestas y el esquema en el que están trabajando:

Database changed
mysql> create table carpet(id int(3), material varchar(10), color varchar(15));
Query OK, 0 rows affected (0.02 sec)

mysql> create table curtain(id int(3), material varchar(10), color varchar(15));
Query OK, 0 rows affected (0.00 sec)

(montón de sentencias de inserción)

mysql> select * from carpet;
+------+-----------+--------------+
| id   | material  | color        |
+------+-----------+--------------+
|    1 | wool      | Light Yellow |
|    2 | wool      | Beige        |
|    3 | polyester | Light Yellow |
|    4 | polyester | Light Red    |
+------+-----------+--------------+
4 rows in set (0.00 sec)

mysql> select * from curtain;
+------+----------+--------------+
| id   | material | color        |
+------+----------+--------------+
|    1 | Velvet   | Purple       |
|    2 | cotton   | White        |
|    3 | cotton   | Light Yellow |
|    4 | cotton   | Light Blue   |
+------+----------+--------------+
4 rows in set (0.00 sec)

Una intersección usa dos declaraciones de selección y trae resultados coincidentes. En este caso, está buscando todas las filas que coincidan con el color 'Amarillo claro'.

No puedo darte un ejemplo en MySQL ya que no lo admite (como puedes ver a continuación, no es necesario para dar los mismos resultados).

Una consulta de unión de dos declaraciones de selección, cada una con una cláusula where que solo permite el color 'Amarillo claro' devolverá los mismos datos. Aunque se puede usar una unión para devolver datos que no coinciden, la cláusula where en cada declaración de selección significa que, de hecho, solo devolverá las filas que desee.

mysql> select id, material, color from carpet
    -> union 
    -> select id, material, color from curtain;
+------+-----------+--------------+
| id   | material  | color        |
+------+-----------+--------------+
|    1 | wool      | Light Yellow |
|    2 | wool      | Beige        |
|    3 | polyester | Light Yellow |
|    4 | polyester | Light Red    |
|    1 | Velvet    | Purple       |
|    2 | cotton    | White        |
|    3 | cotton    | Light Yellow |
|    4 | cotton    | Light Blue   |
+------+-----------+--------------+
8 rows in set (0.00 sec)

Aww, eso es malo, ¿verdad? Por supuesto, no especificamos la cláusula where:

mysql> select id, material, color from carpet where color='Light Yellow'
    -> union
    -> select id, material, color from curtain where color='Light Yellow';
+------+-----------+--------------+
| id   | material  | color        |
+------+-----------+--------------+
|    1 | wool      | Light Yellow |
|    3 | polyester | Light Yellow |
|    3 | cotton    | Light Yellow |
+------+-----------+--------------+
3 rows in set (0.00 sec)

Una combinación entre dos tablas en el color le permitirá devolver las filas de ambas tablas en una sola fila de datos. Puede especificar la unión en las dos tablas para el color del elemento y usar una cláusula where para devolver solo las filas que está buscando.

mysql> select a.id, a.material, a.color, b.id, b.material 
    -> from curtain a join carpet b on a.color=b.color;
+------+----------+--------------+------+-----------+
| id   | material | color        | id   | material  |
+------+----------+--------------+------+-----------+
|    3 | cotton   | Light Yellow |    1 | wool      |
|    3 | cotton   | Light Yellow |    3 | polyester |
+------+----------+--------------+------+-----------+
2 rows in set (0.00 sec)

Como puede ver, esto devolvió solo las filas con un color coincidente y le permitió tener columnas de ambas tablas en una sola fila de su conjunto de resultados.

Ahora, claramente no planeé esto muy bien ya que no tengo otros resultados coincidentes además del 'Amarillo claro' en ambas tablas, así que si agrego algunas entradas más obtenemos esto:

mysql> select * from curtain;
+------+----------+--------------+
| id   | material | color        |
+------+----------+--------------+
|    1 | Velvet   | Purple       |
|    2 | cotton   | White        |
|    3 | cotton   | Light Yellow |
|    4 | cotton   | Light Blue   |
|    5 | Wool     | White        |
|    6 | Fluff    | Beige        |
+------+----------+--------------+
6 rows in set (0.00 sec)

mysql> select * from carpet;
+------+-----------+--------------+
| id   | material  | color        |
+------+-----------+--------------+
|    1 | wool      | Light Yellow |
|    2 | wool      | Beige        |
|    3 | polyester | Light Yellow |
|    4 | polyester | Light Red    |
|    5 | Fluff     | Light Blue   |
+------+-----------+--------------+
5 rows in set (0.00 sec)

Ahora podemos ejecutarlo de nuevo, y esta vez obtener:

mysql> select a.id, a.material, a.color, b.id, b.material 
    -> from curtain a join carpet b on a.color=b.color;
+------+----------+--------------+------+-----------+
| id   | material | color        | id   | material  |
+------+----------+--------------+------+-----------+
|    3 | cotton   | Light Yellow |    1 | wool      |
|    3 | cotton   | Light Yellow |    3 | polyester |
|    4 | cotton   | Light Blue   |    5 | Fluff     |
|    6 | Fluff    | Beige        |    2 | wool      |
+------+----------+--------------+------+-----------+
4 rows in set (0.00 sec)

¡Oh, no!

Aquí es donde ahora usamos la cláusula join y where juntas:

mysql> select a.id, a.material, a.color, b.id, b.material 
    -> from curtain a join carpet b on a.color=b.color 
    -> where a.color='Light Yellow';
+------+----------+--------------+------+-----------+
| id   | material | color        | id   | material  |
+------+----------+--------------+------+-----------+
|    3 | cotton   | Light Yellow |    1 | wool      |
|    3 | cotton   | Light Yellow |    3 | polyester |
+------+----------+--------------+------+-----------+
2 rows in set (0.00 sec)

Verá, en SQL a menudo hay más formas de obtener el mismo resultado a través de diferentes medios que variaciones de los mismos datos en sus tablas.

Editar:De acuerdo, si solo desea filas donde todas los datos coinciden, simplemente inclúyalos en la sintaxis de unión:

mysql> select a.id, a.material, a.color, b.id, b.material 
    -> from curtain a 
    -> join carpet b on a.color=b.color
    -> and a.id=b.id
    -> where a.color='Light Yellow';
+------+----------+--------------+------+-----------+
| id   | material | color        | id   | material  |
+------+----------+--------------+------+-----------+
|    3 | cotton   | Light Yellow |    3 | polyester |
+------+----------+--------------+------+-----------+
1 row in set (0.00 sec)

Como puede ver, ahora le decimos a la unión que tanto el id y color los campos deben coincidir entre las dos tablas, y los resultados hablan por sí mismos. Ahora, en este caso, técnicamente todavía no coincidió con TODAS las columnas ya que el material es diferente. Si quisiera buscar más coincidencias, la consulta no devolvería ningún resultado ya que no tengo registros coincidentes donde coincidan la identificación, el material Y el color, pero la sintaxis sería la siguiente:

mysql> select a.id, a.material, a.color, b.id, b.material 
    -> from curtain a 
    -> join carpet b on a.color=b.color
    -> and a.id=b.id
    -> and a.material=b.material
    -> where a.color='Light Yellow';
Empty set (0.00 sec)

Sin embargo, en ese sentido, en la mayoría de los casos, no desea todos las columnas para que coincidan. Muy a menudo, las tablas tienen una identificación que solo se usa para esa tabla y es un valor que se incrementa automáticamente. Desea usarlo para identificar una fila única en eso tabla, pero no para usarla para hacer coincidir tablas no relacionadas. En todo caso, le habría sugerido que hiciera coincidir el material y el color, pero no incluyera la identificación.