Cuando creamos una UNION y queremos ver sus resultados ordenados … podemos encontrarnos con el problema de que no podemos conseguirlo. ¿Por qué? Porque el Firebird no permite que escribamos el nombre de una columna en una cláusula ORDER BY de un SELECT que se usará en una UNION.

Sin embargo, necesitamos ver el conjunto resultado ordenado. ¿Cómo lo conseguimos?

Ejemplo.

Tenemos una tabla llamada CLIENTES y otra tabla llamada PROSPECTOS. Los prospectos son los clientes potenciales, aquellas personas o empresas a las cuales aún no les hemos vendido pero ya nos hemos entrevistado con ellas y puede ser que les vendamos más adelante. O sea, son nuestros posibles futuros clientes.

UNION1

Captura 1. Si haces clic en la imagen la verás más grande

UNION2

Captura 2. Si haces clic en la imagen la verás más grande

En la Captura 1. vemos algunos datos de nuestros clientes, y en la Captura 2. vemos algunos datos de nuestros prospectos. Ahora quisiéramos unirlos para verlos a todos juntos, pero deseamos verlos ordenados alfabéticamente por nombre. Así que escribimos:

Listado 1.

SELECT
   CLI_NOMBRE,
   CLI_DIRECC,
   CLI_TELEFO,
   CLI_EMAILX
FROM
   CLIENTES
ORDER BY
   CLI_NOMBRE

UNION ALL

SELECT
   PRO_NOMBRE,
   PRO_DIRECC,
   PRO_TELEFO,
   PRO_EMAILX
FROM
   PROSPECTOS

Escribimos la cláusula ORDER BY en el primer SELECT y el Firebird nos responde con el mensaje: “Token unknown – line 11, column 4. UNION.

No funcionó, no aceptó que escribamos UNION después de escribir ORDER BY. Así que ahora probamos:

Listado 2.

SELECT
   CLI_NOMBRE,
   CLI_DIRECC,
   CLI_TELEFO,
   CLI_EMAILX
FROM
   CLIENTES

UNION ALL

SELECT
   PRO_NOMBRE,
   PRO_DIRECC,
   PRO_TELEFO,
   PRO_EMAILX
FROM
   PROSPECTOS
ORDER BY
   PRO_NOMBRE

Donde escribimos la cláusula ORDER BY en el segundo SELECT. Y la respuesta del Firebird es: “Invalid command. Invalid ORDER BY clause.

O sea que … ¡¡¡tampoco funcionó!!!

Sin embargo, deseamos ver al resultado de esa UNION ordenado por nombres. ¿Cómo lo conseguimos?

Tenemos dos técnicas:

  1. Usando un número de columna
  2. Usando una tabla derivada

Ordenando una UNION usando un número de columna:

Listado 3.

SELECT
   CLI_NOMBRE,
   CLI_DIRECC,
   CLI_TELEFO,
   CLI_EMAILX,
   'C' AS CLI_ORIGEN
FROM
   CLIENTES

UNION ALL

SELECT
   PRO_NOMBRE,
   PRO_DIRECC,
   PRO_TELEFO,
   PRO_EMAILX,
   'P' AS CLI_ORIGEN
FROM
   PROSPECTOS
ORDER BY
   1

Ordenando una UNION usando una tabla derivada:

Listado 4.

SELECT
   CLI_NOMBRE,
   CLI_DIRECC,
   CLI_TELEFO,
   CLI_EMAILX,
   CLI_ORIGEN
FROM (
      SELECT
         CLI_NOMBRE,
         CLI_DIRECC,
         CLI_TELEFO,
         CLI_EMAILX,
         'C' AS CLI_ORIGEN
      FROM
         CLIENTES
 
      UNION ALL

      SELECT
         PRO_NOMBRE,
         PRO_DIRECC,
         PRO_TELEFO,
         PRO_EMAILX,
         'P' AS CLI_ORIGEN
      FROM
         PROSPECTOS
     )
ORDER BY
   CLI_NOMBRE

¡¡¡Y ahora sí funcionó!!!

UNION3

Captura 3. Si haces clic en la imagen la verás más grande

Como podemos ver, a las 7 filas que teníamos en nuestra tabla de CLIENTES se le agregaron las 2 filas que teníamos en la tabla de PROSPECTOS y ahora nuestro conjunto resultado tiene 9 filas. Y además, vemos a todas esas filas ordenadas alfabéticamente por nombre. ¡¡¡Excelente!!!

Adicionalmente, habrás notado que tenemos una nueva columna, llamada CLI_ORIGEN, esa es una técnica muy usada cuando se realiza una UNION para poder distinguir el origen (o sea, de donde proviene) cada fila. En nuestro caso si hay una letra ‘C’ significa que el origen de esa fila es la tabla de CLIENTES, y si hay una letra ‘P’ entonces significa que el origen de esa fila es la tabla de PROSPECTOS. No siempre es necesario tener una columna que nos informe del origen de la fila, pero si alguna vez necesitas conocer ese dato, esta es la forma de hacerlo.

Explicación:

En el Listado 3. hemos usado un número que indica la posición de la columna que nos interesa (1=CLI_NOMBRE, 2=CLI_DIRECC, etc.). Podemos ordenar por cualquier columna, pero siempre recordando que debemos usar el número de esa columna, nunca su nombre. Y si queremos ordenar de mayor a menor entonces debemos usar la palabra DESCENDING, como en: “ORDER BY 1 DESCENDING”

En el Listado 4. creamos una tabla derivada que es la UNION entre la tabla CLIENTES y la tabla PROSPECTOS. El conjunto resultado que obtuvimos no está ordenado pero como ya sabemos el conjunto resultado de una subconsulta siempre es una tabla (y las tablas derivadas son una subconsulta que se usa después de la cláusula FROM). Entonces, y por lo tanto, podemos ordenar a esa tabla virtual.

Y así hemos solucionado nuestro problema.

Artículos relacionados:

El resultado de un SELECT es una tabla

Entendiendo subconsultas y tablas derivadas

Tablas derivadas

Optimizando un SELECT al usar una tabla derivada

Optimizando los JOIN

Optimizando las subconsultas

El índice del blog Firebird21

El foro del blog Firebird21