De DBF a SQL (11). Relacionando una tabla con otra tabla

En Visual FoxPro solamente hay una forma de relacionar una tabla con otra tabla, en SQL tenemos cuatro formas.

Las cláusulas del comando SELECT que nos permiten relacionar a una tabla con otra tabla son:

  • INNER JOIN. Requiere que para cada fila de la tabla A exista una fila en la tabla B (esta es la forma que también existe en Visual FoxPro).
  • LEFT JOIN. Los datos de la tabla de la izquierda (left, en inglés) se muestran siempre, sí o sí. Los datos de la tabla de la derecha se muestran solamente si se los pudo emparejar, en caso contrario se muestra NULL
  • RIGHT JOIN. Los datos de la tabla de la derecha (right, en inglés) se muestran siempre, sí o sí. Los datos de la tabla de la izquierda se muestran solamente si se los pudo emparejar, en caso contrario se muestra NULL
  • FULL JOIN. Se muestran todas las filas de ambas tablas, poniendo NULL cuando no se puede emparejar

Aquí, la palabra «emparejar» significa que ambas tablas tengan el mismo valor en las columnas por la cuales se están relacionando.

La palabra JOIN significa «juntar».  Cuando se juntan de forma interna (INNER JOIN) a cada fila de la tabla A le debe corresponder una fila de la tabla B. Si una fila de la tabla A no tiene una fila correspondiente en la tabla B entonces esa fila es ignorada, no existe.

Cuando se juntan externamente (LEFT JOIN, RIGHT JOIN, FULL JOIN) entonces no es requisito que para cada fila de la tabla A exista una fila en la tabla B. Cuando no existe se coloca NULL en esas columnas.

IMPORTANTE: Recuerda que en SQL la palabra NULL significa «desconocido» o «no disponible». No significa «nulo», como algunos piensan.

¿Cuál es el beneficio de juntar externamente?

Cuando juntamos internamente (mediante INNER JOIN) obtenemos las filas que existen en ambas tablas. Cuando juntamos externamente (mediante LEFT JOIN, RIGHT JOIN, FULL JOIN) podemos también obtener datos que no existen en una de las tablas.

Por ejemplo, si relacionamos “internamente” la tabla ALUMNOS con la tabla EXÁMENES podemos mostrar los datos de todos los alumnos que fueron examinados, pero solamente de ellos, no podríamos saber cuales fueron los alumnos que por algún motivo no fueron examinados. En cambio si las relacionamos “externamente” podemos mostrar los datos de todos los alumnos, hayan sido examinados o no.

Si relacionamos “internamente” las tablas PRODUCTOS y VENTAS podemos mostrar los datos de todos los productos vendidos. Pero no podríamos saber cuales fueron los productos que no se vendieron. En cambio si relacionamos esas tablas “externamente” sí podríamos saber cuales productos no se vendieron.

Si relacionamos «internamente» la tabla CLIENTES con la tabla COBRANZAS podríamos saber a cuales clientes se les cobró el mes pasado, pero no sabríamos a cuales clientes no se les cobró el mes pasado. En cambio si relacionamos a esas tablas «externamente», también podríamos saber a cuales clientes no se les cobró.

Usando la cláusula JOIN para relacionar tablas

A continuación veremos algunos ejemplos de los resultados que se obtienen al relacionar dos tablas entre sí. Para ello usaremos la tabla CLIENTES y la tabla VENTASCAB (cabecera de las ventas).

Captura 1. Las filas de nuestra tabla de CLIENTES

Si observaste la Captura 1. habrás notado que faltan los códigos «00005» y «00011», eso fue hecho a propósito para entender los siguientes ejemplos.

Captura 2. Las filas de nuestra tabla VENTASCAB

La tabla VENTASCAB tiene 18 filas, como puedes verificar contándolas.

Ejemplo 1. Relacionando internamente dos tablas

Captura 3. Relacionando internamente la tabla VENTASCAB con la tabla CLIENTES

En la Captura 2. vimos que la tabla VENTASCAB tiene 18 filas, sin embargo en la Captura 3. estamos viendo solamente 15 filas, ¿por qué eso? porque las filas en donde la columna VTC_CODCLI tiene el valor «00005» o el valor «00011» no se mostraron. Como no se pudo relacionar esas filas entonces simplemente no se muestran.

Habrás notado también que se escribió sólo JOIN, no se escribió INNER JOIN. ¿Por qué eso? porque como INNER JOIN es la forma de relacionamiento más utilizada, es opcional escribir la palabra INNER. Si se escribe solamente JOIN (sin antes escribir INNER, LEFT, RIGHT, FULL) el SQL entiende que es un INNER JOIN. Por eso, ya depende de cada uno escribir INNER JOIN o escribir solamente JOIN. Lo puedes hacer como más te guste.

Ejemplo 2. Relacionando por la izquierda a dos tablas

Captura 4. Al relacionar mediante un LEFT JOIN, también se muestran las filas de VENTASCAB que no se emparejaron con CLIENTES

Ejemplo 3. Averiguando cuales son las filas problemáticas

En la Captura 4. podemos ver que hay 3 filas que tienen NULL en la columna CLI_NOMBRE y evidentemente eso está mal, se debería corregir. Pero…¿y si la tabla no tiene 18 filas como en ese ejemplo sino miles y miles de filas? Estar revisando las filas una por una para descubrir a las que tienen NULL sería una gran pérdida de tiempo. Afortunadamente, con un simple comando SELECT podemos descubrir cuales son esas filas.

Captura 5. Hallando las filas de la tabla VENTASCAB cuyo Código de Cliente no existe en la tabla de CLIENTES.

Aquí el truco fue poner en la cláusula WHERE la condición de IS NULL. Entonces, se obtienen todas las filas de la tabla VENTASCAB que no fueron emparejadas.

Ejemplo 4. Obteniendo los códigos que no se emparejaron

En la Captura 5. podemos observar que el código «00005» aparece 2 veces. En este caso no hay problema con eso, porque solamente 3 filas tienen problemas, pero en la vida real un mismo código faltante podría repetirse cientos o miles de veces, una vez por cada fila problemática. Evidentemente que no sería práctico observar tantas y tantas filas. Y es que agregando una fila con el código «00005» a la tabla de CLIENTES se resolvería el problema de todos los códigos «00005» de la tabla VENTASCAB. Entonces, ¿cómo hacemos para que cada código problemático se vea una sola vez?

Usando la cláusula DISTINCT, que ya conocemos.

Captura 6. Viendo solamente una vez cada código de cliente faltante

Y ahora sí, cada código de cliente que existe en la tabla VENTASCAB y que no existe en la tabla CLIENTES es mostrado una sola vez. El truco fue mostrar una sola columna y usar la cláusula DISTINCT.

Ejemplo 5. Obteniendo los clientes a los cuales no se les ha vendido

¿Hay algunos clientes a los cuales no se les ha vendido? ¿Cuáles son esos clientes? Podemos averiguarlo muy fácilmente.

Captura 7. Los clientes a los cuales no se les vendió

Si observas la Captura 3. o si observas la Captura 4., verás que en ninguna fila se encuentra el código de cliente «00003». O sea, ninguna venta se le realizó a ese cliente. Y en la Captura 7. puedes ver como se hizo para descubrirlo.

En este caso lo que hicimos fue obtener los datos de los clientes que existen en la tabla de CLIENTES pero que no existen en la tabla VENTASCAB.

Conclusión:

En VFP solamente tenemos una forma de relacionar a dos tablas entre sí. En SQL tenemos cuatro formas. Cada una de esas cuatro formas nos puede resultar muy útil, según iremos viendo en los ejemplos de los siguientes artículos.

Cuando relacionamos a dos tablas de forma «interna» (usando INNER JOIN o sólo JOIN si queremos abreviar) es requisito que las filas de ambas tablas se puedan emparejar.

Cuando relacionamos a dos tablas de forma «externa» (usando LEFT JOIN, RIGHT JOIN, o FULL JOIN) no es requisito que las dos tablas se puedan emparejar, en los casos en que no se emparejan la palabra NULL aparece en la columna. Por lo tanto, si vemos NULL sabemos que no hay emparejamiento. Recuerda: en SQL la palabra NULL significa «desconocido» o «no aplicable». No significa «nulo».

En SQL se dice que dos filas están emparejadas cuando tienen el mismo valor en la columna que las relaciona. Por ejemplo, si en la columna VTC_CODCLI de la tabla VENTASCAB existe el código «00012» y en la columna CLI_CODIGO de la tabla CLIENTES también existe el código «00012», entonces ambas tablas están emparejadas en esas filas.

Comentario 1: ¿Ya te has dado cuenta que el comando SELECT es muchísimo más poderoso que el comando BROWSE?

Comentario 2: ¿Ya te has dado cuenta que para obtener los mismos resultados deberías escribir mucho más si no usas SQL?

Artículos relacionados:

De DBF a SQL (1). Introducción

De DBF a SQL (2). Reemplazando comandos

De DBF a SQL (3). Entendiendo a los cursores

De DBF a SQL (4). Ejemplos de usar SELECT con una sola tabla

De DBF a SQL (5). Las funciones agrupadas

De DBF a SQL (6). Agrupando filas

De DBF a SQL (7). Poniéndoles condiciones a los grupos

De DBF a SQL (8). Ordenando las filas

De DBF a SQL (9). Uniendo tablas

De DBF a SQL (10). Obteniendo las primeras filas de una tabla

De DBF a SQL (12). Relacionando una tabla consigo misma

De DBF a SQL (13). Relacionando a varias tablas entre sí

De DBF a SQL (14). Más sobre el uso de DISTINCT

De DBF a SQL (15). Usando subconsultas

De DBF a SQL (16). Más sobre las subconsultas

De DBF a SQL (17). Ejemplos de subconsultas

De DBF a SQL (18). Paginación

De DBF a SQL (19). Hallando los porcentajes sobre un total

De DBF a SQL (20). Los operadores especiales de comparación

De DBF a SQL (21). La técnica de los dos cursores

De DBF a SQL (22). Optimizando el uso del operador de comparación especial IN

De DBF a SQL (23). Usando la función CAST()

De DBF a SQL (24). Buscando texto

De DBF a SQL (25).  Creando tablas y cursores

De DBF a SQL (26). INSERT, UPDATE, y DELETE, con subconsultas

De DBF a SQL (27). Entendiendo Cliente/Servidor

De DBF a SQL (28). Conectándose a un Servidor

De DBF a SQL (29). Las cadenas de conexión ODBC a los motores SQL más populares 

De DBF a SQL (30). Conectándose mediante ADO a las bases de datos

De DBF a SQL (31). Optimizando la escritura de los SELECT

De DBF a SQL (32). Mejorando la estética de los SELECT 

De DBF a SQL (33). Usando la función SQLEXEC()

De DBF a SQL (34). Enviándole parámetros a la función SQLEXEC()

El índice del blog VFPavanzado