Relacionando dos tablas: la forma vieja y la forma nueva

2 comentarios

En Firebird, cuando queremos relacionar dos tablas (o conjuntos de resultados) entre sí tenemos dos posibilidades:

  1. Usando la forma vieja
  2. Usando la forma nueva

Caso 1. Usando la forma vieja

Esta sintaxis fue establecida en el año 1989. Las tablas se listan separadas por comas después de la cláusula FROM y la condición que las relaciona se pone en la cláusula WHERE. No hay una sintaxis especial que distinga cuales de las condiciones del WHERE son para filtrar filas y cuales son para relacionar tablas, se supone que mirando la sentencia el desarrollador sabrá cual es cual.

¿Problemas?

  • La cláusula WHERE puede volverse muy larga y muy complicada de leer porque se la usa para relacionar tablas y también para filtrar filas
  • Solamente se pueden relacionar tablas que tengan valores idénticos, si una de las tablas tiene NULL en una columna no se podrá hacer la relación. En otras palabras: solamente se puede hacer un INNER JOIN, no se pueden hacer OUTER JOIN.

Sintaxis:

SELECT
   MiColumna1,
   MiColumna2
FROM
   MiTabla1,
   MiTabla2
WHERE
   MiCondición

Caso 2. Usando la forma nueva

Esta sintaxis fue establecida en el año 1992. La tabla principal se coloca después de la cláusula FROM y la tabla secundaria se coloca después de la cláusula JOIN, la condición que las relaciona se coloca después de ON. Por lo tanto se puede distinguir fácilmente cual es la condición usada para relacionar a la tablas y cual es la condición usada para filtrar filas, no hay confusión posible.

¿Ventajas?

  • Es muy fácil saber cual es la condición usada para relacionar a las dos tablas
  • Es muy fácil saber cual es la condición usada para filtrar filas
  • La cláusula WHERE es más corta y por lo tanto más fácil de leer que cuando se usa la forma vieja
  • Se puede usar tanto INNER JOIN como OUTER JOIN

Sintaxis:

SELECT
   MiColumna1,
   MiColumna2
FROM
   MiTabla1
JOIN
   MiTabla2
      ON MiCondición

Cuidado:

Tú puedes elegir cualquiera de las dos formas para relacionar tablas pero NUNCA debes mezclarlas. En un SELECT o usas la forma vieja o usas la forma nueva, no las mezcles, porque si las mezclas eso solamente te ocasionará problemas y ningún beneficio.

Recomendación:

La forma nueva es mejor, por eso se la inventó, por eso existe. Si ya tienes SELECTs escritos con la forma vieja y funcionan bien entonces déjalos como están, no los toques, pero para escribir todos tus nuevos SELECTs usa la forma nueva porque es la que verás cada vez más en todos los libros y documentos sobre SQL. Y es además la que siempre se usa en este blog.

Artículos relacionados:

Entendiendo a los JOIN

JOIN implícito y JOIN explícito

El índice del blog Firebird21

 

Entendiendo subconsultas y tablas derivadas

6 comentarios

El lenguaje SQL nos permite escribir un SELECT en muchos lugares, veamos algunos ejemplos:

Ejemplo 1. Un SELECT simple

SELECT
   MiColumna1,
   MiColumna2
FROM
   MiTabla

En este caso se escribió solamente un SELECT, es útil para consultas sencillas pero cuando las consultas se complican ya no será suficiente.

Ejemplo 2. Un SELECT con una subconsulta

SELECT
   MiColumna1,
   (SELECT MiColumna2 FROM MiTabla2 WHERE MiCondición)
FROM
   MiTabla

En este ejemplo hemos reemplazado a MiColumna2 por una subconsulta, o sea por un SELECT dentro de otro SELECT. El SELECT que está entre paréntesis es la subconsulta. Fíjate que además del nombre de la tabla se escribió la cláusula WHERE ¿por qué eso? porque la subconsulta debe devolver una sola columna y una sola fila.

Si la subconsulta devuelve más de una columna entonces verás el error: “Count of column list and variable list do not match”. O sea que se esperaba una sola columna pero la subconsulta está devolviendo más de una columna.

Si devuelve una sola columna pero más de una fila entonces el mensaje de error que verás será: “Multiple rows in singleton select”. ¿qué significa esa frase? que la subconsulta debería devolver una sola fila pero está devolviendo más de una fila.

La cláusula WHERE sirve justamente para poner una condición que estás seguro que se cumple para una sola fila. Además de la cláusula WHERE también podrías usar, dependiendo del caso, las cláusulas FIRST 1, ó ROWS 1 ó DISTINCT o las funciones agregadas MAX(), MIN(), etc. Lo que debes recordar es que la subconsulta debe devolver una fila y solamente una fila. Puede devolver cero filas, y en ese caso el valor de la columna será NULL (en SQL un valor de NULL significa “valor desconocido”) pero jamás más de una fila.

Ejemplo 3. Un SELECT a continuación del FROM

SELECT
   MiColumna1,
   MiColumna2
FROM
   (SELECT MiColumna1, MiColumna2 FROM MiTabla)

Aquí el SELECT interno se escribió después de la cláusula FROM. En estos casos no se le llama subconsulta sino que se le llama tabla derivada.

Para que funcione, la cantidad de columnas de la tabla derivada siempre debe ser igual o mayor a la cantidad de columnas del SELECT principal, nunca puede ser menor (y a la tabla principal si lo deseas puedes agregarle columnas que tengan valores constantes, como 17, 21, ‘Asunción’, etc.). Y los nombres de las columnas deben coincidir, no puedes usar una columna en el SELECT principal que no hayas usado en la tabla derivada.

Fíjate que la subconsulta debe devolver una sola columna pero la tabla derivada puede devolver varias columnas.

Ejemplo 4. Una subconsulta en la cláusula GROUP BY

SELECT
   MiColumna1,
   (SELECT MiColumna2 FROM MiTabla2 WHERE MiCondición)
FROM
   MiTabla
GROUP BY
   MiColumna1,
   (SELECT MiColumna2 FROM MiTabla2 WHERE MiCondición)

En este caso, la subconsulta se usó también luego de la cláusula GROUP BY, eso es necesario porque todas las columnas que se incluyen en el SELECT principal y que no son funciones agregadas también deben encontrarse a continuación de la cláusula GROUP BY.

Ejemplo 5. Una subconsulta en la cláusula ORDER BY

SELECT
   MiColumna1,
   MiColumna2
FROM
   MiTabla
ORDER BY
   (SELECT MiColumna3 FROM MiTabla2 WHERE MiCondición)

Aquí como puedes ver la subconsulta se escribió a continuación de la cláusula ORDER BY y por lo tanto el SELECT principal será ordenado por el contenido de la subconsulta.

Ejemplo 6. Un subconsulta en el JOIN

SELECT
   MiColumna1,
   MiColumna2
FROM
   MiTabla
JOIN
   MiTabla2
      ON MiColumna = (SELECT MiOtraColumna FROM MiOtraTabla)

También puede usarse una subconsulta en el JOIN, sea éste del tipo que sea (INNER, LEFT, RIGHT, FULL, CROSS, NATURAL)

Ejemplo 7. Insertando, modificando o borrando filas desde una subconsulta

Si necesitas insertarle datos a una tabla y los datos que necesitas se encuentran en otra u otras tablas la forma más rápida es hacerlo con una subconsulta:

INSERT INTO
MiTabla
   (MiColumna1, MiColumna2, MiColumna3)
   SELECT MiValor1, MiValor2, MiValor3 FROM MiOtraTabla

También puedes usar una subconsulta para establecer la condición que necesitas para modificar o borrar filas. En general se usan subconsultas cuando las filas que se quiere insertar, modificar o borrar son muchas.

Conclusión:

Como seguramente habrás deducido luego de ver los ejemplos anteriores, las subconsultas pueden usarse en muchos lugares, prácticamente puedes usarlas en cualquier lugar donde necesites el valor de una columna.

Hay muchos ejemplos más que podría escribir pero con los anteriores supongo que ya tienes bien clara la idea.

¿Es conveniente usar subconsultas?

A veces sí, a veces no. En ocasiones es lo mejor que puedes hacer y en ocasiones hay mejores alternativas así que debes tratarlas como una herramienta más, algo que te puede ayudar a conseguir los resultados que estás buscando. Pero debes recordar que en general usar subconsultas es más lento que no usarlas y por lo tanto debes siempre verificar que no exista una mejor opción.

Artículos relacionados:

Tablas derivadas

El índice del blog Firebird21