Notación de comparación de tupla para simplificar consultas

SQL permite comparar varias columnas con una única operación, usando la notación de tupla; p.ej., (nombre, apellido) = ('Fran', 'García'). Se trata de una notación muy compacta y útil, que puede llegar a simplificar mucho algunas consultas que requieren de varias subconsultas sobre la misma tabla. Veamos un ejemplo.

Supongamos la siguiente BD, en la que tenemos una tabla para personas y otra para tiendas. Hemos simplificado las tablas para dejar solamente los campos que nos hacen falta, de entre los cuales destacamos la calle y la ciudad donde viven las personas o están las tiendas

Persona
+----+-------------+-----------------+----------+
| id | nombre      | calle           | ciudad   |
+----+-------------+-----------------+----------+
|  1 | Ana Abad    | Avd. América    | Alicante |
|  2 | Bea Bez     | Bertendona      | Bilbao   |
|  3 | Carlos Cruz | Ciriaco Garrido | Cádiz    |
|  4 | Ana Abad    | Duque de Lerma  | Durango  |
+----+-------------+-----------------+----------+
Tienda
+----+----------------+---------+
| id | calle          | ciudad  |
+----+----------------+---------+
|  1 | Avd. América   | Durango |
|  2 | Duque de Lerma | Cádiz   |
|  3 | Bertendona     | Bilbao  |
+----+----------------+---------+

Nos piden encontrar las personas que sean vecinas de alguna tienda. Es decir, personas que vivan en la misma ciudad y calle donde haya una tienda. Por simple inspección podemos comprobar que “Bea Bez” es la única que cumple tal condición.

Para resolver esta consulta hemos decidido usar el operador in con subconsultas en la tabla Tienda.

Una solución apresurada y errónea sería la siguiente

MAL
select *
from Persona
where calle in (select calle 
                from Tienda) 
  and ciudad in (select ciudad 
                 from Tienda);

Es errónea porque no se garantiza en ningún momento que las personas seleccionadas cumplan que su calle y ciudad sean simultáneamente la calle y la ciudad de alguna tienda de la tabla Tienda. Podría ocurrir que la calle sea de una tienda y la ciudad de otra tienda diferente.

Para mejorarlo podemos escribir esta consulta, que ya garantiza lo anterior:

MEJORABLE
select *
from Persona P
where calle in (select calle 
                from Tienda
                where ciudad=P.ciudad);

Podríamos evitar la correlación y simplificar la consulta usando la notación de tuplas en comparaciones:

BIEN
select *
from Persona P
where (calle, ciudad) in (select calle, ciudad 
                          from Tienda);

La notación de tupla garantiza que la pareja calle y ciudad de cada persona se comparan con parejas calle y ciudad de las tiendas, evitándose el problema la solución errónea anterior y resultando en una consulta más fácil de entender.

No hay comentarios:

Publicar un comentario