Normalmente cuando escribimos un SELECT los resultados se muestran en una fila tras otra pero a veces podría interesarnos ver los resultados en una columna tras otra, o sea: convertir las filas en columnas.

Una forma de conseguirlo es con las tablas CTE (Common Table Expression) que como ya hemos visto en artículos anteriores son tablas virtuales.

Desde luego que para que esto sea manejable la cantidad de filas que convertiremos en columnas debe ser pequeña. Si nuestro SELECT nos devuelve miles o millones de filas no vamos a convertirlas a todas ellas en columnas, nadie siquiera miraría semejante monstruosidad y habríamos desperdiciado nuestro tiempo.

Ejemplo:

Tenemos una tabla de BANCOS que tiene 16 filas y queremos ver las primeras 4 filas como columnas.

COLUMNAS1

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

Para ello escribimos la siguiente consulta:

WITH MisBancos AS (
   SELECT
      BAN_CODSUC,
      BAN_IDENTI,
      BAN_NOMBRE
   FROM
      BANCOS
)

SELECT
   M.BAN_NOMBRE,
   N.BAN_NOMBRE,
   O.BAN_NOMBRE,
   P.BAN_NOMBRE
FROM
   BANCOS B
JOIN
   MISBANCOS M
      ON B.BAN_CODSUC = M.BAN_CODSUC AND
         B.BAN_IDENTI + 0 = M.BAN_IDENTI AND
         M.BAN_IDENTI = 1
JOIN
   MISBANCOS N
      ON B.BAN_CODSUC = N.BAN_CODSUC AND
         B.BAN_IDENTI + 1 = N.BAN_IDENTI AND
         N.BAN_IDENTI = 2
JOIN
   MISBANCOS O
      ON B.BAN_CODSUC = O.BAN_CODSUC AND
         B.BAN_IDENTI + 2 = O.BAN_IDENTI AND
         O.BAN_IDENTI = 3
JOIN
   MISBANCOS P
      ON B.BAN_CODSUC = P.BAN_CODSUC AND
         B.BAN_IDENTI + 3 = P.BAN_IDENTI AND
         P.BAN_IDENTI = 4
WHERE
   B.BAN_CODSUC = 0 AND
   B.BAN_IDENTI > 0
ROWS
 1

Y este es el resultado que obtenemos:

COLUMNAS2

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

Donde como puedes ver los nombres de los Bancos se muestran en columnas diferentes.

Otro método:

Podemos obtener el mismo resultado anterior usando una tabla que siempre tenga una fila y nunca más ni menos de una fila. Aquí usamos la tabla interna RDB$DATABASE porque está garantizada que siempre tendrá exactamente una fila pero tú puedes usar cualquier otra tabla si quieres.

WITH MisBancos AS (
   SELECT
      BAN_CODSUC,
      BAN_IDENTI,
      BAN_NOMBRE
   FROM
      BANCOS
)

SELECT
   M.BAN_NOMBRE,
   N.BAN_NOMBRE,
   O.BAN_NOMBRE,
   P.BAN_NOMBRE
FROM
   RDB$DATABASE
JOIN
   MISBANCOS M
      ON M.BAN_IDENTI = 1
JOIN
   MISBANCOS N
      ON N.BAN_IDENTI = 2
JOIN
   MISBANCOS O
      ON O.BAN_IDENTI = 3
JOIN
   MISBANCOS P
      ON P.BAN_IDENTI = 4

¿Cuál es el truco?

  1. Crear una tabla CTE
  2. Para cada columna que deseamos mostrar hacerle un JOIN a nuestra tabla principal con la tabla CTE. En ese JOIN establecer una relación entre ellas (en este ejemplo esa relación estaba dada por los valores de la columna BAN_IDENTI).

Artículos relacionados:

Usando CTE (Common Table Expression)

Otro ejemplo de CTE: ventas semanales

Usando una cross-table

¿Por qué usar una cross-table?

Usando varias CTE en una vista o en un stored procedure

El índice del blog Firebird21