🧚 ¡Oye! Beekeeper Studio es una GUI de bases de datos rápida, moderna y de código abierto Descarga
7 de enero de 2026 Por Matthew Rathbone

Una tabla dinámica (pivot) convierte filas en columnas: una fila por grupo y una columna por cada valor de otro campo, por ejemplo una columna por trimestre. En SQL la construyes con CASE dentro de una función de agregación como SUM, agrupando por lo que deba representar cada fila. Los ejemplos funcionan en PostgreSQL, MySQL, SQLite y SQL Server.

Cómo hacer una tabla dinámica en SQL

Escribe una agregación por cada columna de salida. El CASE que va dentro solo deja pasar las filas que pertenecen a esa columna, y GROUP BY genera una fila por grupo:

SELECT
  row_column,
  SUM(CASE WHEN pivot_column = 'value 1' THEN amount ELSE 0 END) AS value_1,
  SUM(CASE WHEN pivot_column = 'value 2' THEN amount ELSE 0 END) AS value_2
FROM table_name
GROUP BY row_column;

Aquí cada producto tiene una fila, con sus unidades de cada trimestre una junto a otra:

-- Input: sales
-- product  | quarter | units
-- ---------+---------+------
-- Keyboard | Q1      | 120
-- Keyboard | Q2      | 95
-- Monitor  | Q1      | 40
-- Monitor  | Q2      | 55
-- Mouse    | Q2      | 210

SELECT
  product,
  SUM(CASE WHEN quarter = 'Q1' THEN units ELSE 0 END) AS q1,
  SUM(CASE WHEN quarter = 'Q2' THEN units ELSE 0 END) AS q2
FROM sales
GROUP BY product
ORDER BY product;

-- Output:
-- product  | q1  | q2
-- ---------+-----+----
-- Keyboard | 120 | 95
-- Monitor  | 40  | 55
-- Mouse    | 0   | 210

Reglas que debes conocer

  • Tú nombras cada columna. SQL no puede crear columnas a partir de los datos, así que un tercer trimestre necesita una tercera línea CASE. Si la lista de valores cambia constantemente, arma la consulta en el código de tu aplicación.
  • ELSE 0 es solo para SUM y conteos. Convierte una combinación faltante en 0 en lugar de NULL. Con AVG, MIN o MAX, omite el ELSE, o los ceros contarán como valores reales:
-- Input: the sales table above

SELECT
  product,
  ROUND(AVG(CASE WHEN quarter = 'Q1' THEN units ELSE 0 END), 1) AS q1_else_0,
  ROUND(AVG(CASE WHEN quarter = 'Q1' THEN units END), 1) AS q1_no_else
FROM sales
GROUP BY product
ORDER BY product;

-- Output:
-- product  | q1_else_0 | q1_no_else
-- ---------+-----------+-----------
-- Keyboard | 60.0      | 120.0
-- Monitor  | 20.0      | 40.0
-- Mouse    | 0.0       | NULL

Sintaxis alternativa

También te encontrarás con FILTER en PostgreSQL y SQLite, y con el operador PIVOT en SQL Server. Ambos dejan una combinación faltante como NULL en vez de 0:

-- Input: the sales table above

-- PostgreSQL and SQLite
SELECT
  product,
  SUM(units) FILTER (WHERE quarter = 'Q1') AS q1,
  SUM(units) FILTER (WHERE quarter = 'Q2') AS q2
FROM sales
GROUP BY product
ORDER BY product;

-- SQL Server
SELECT product, [Q1] AS q1, [Q2] AS q2
FROM (SELECT product, quarter, units FROM sales) AS src
PIVOT (SUM(units) FOR quarter IN ([Q1], [Q2])) AS p
ORDER BY product;

-- Output:
-- product  | q1   | q2
-- ---------+------+----
-- Keyboard | 120  | 95
-- Monitor  | 40   | 55
-- Mouse    | NULL | 210

En código de MySQL verás seguido SUM(IF(quarter = 'Q1', units, 0)), una forma más corta de escribir la versión con CASE. La extensión tablefunc de PostgreSQL también incluye la función crosstab(); consulta cómo crear tablas dinámicas en PostgreSQL con crosstab().

¿Cuándo conviene usar una tabla dinámica?

Usa pivot cuando una lista de filas sería más fácil de leer como cuadrícula. Estas son las razones más comunes.

Comparar una métrica lado a lado

Pon los valores que quieres comparar (días, trimestres, regiones) uno junto a otro en una sola fila, en vez de dispersos en una lista larga.

Mostrar más de una métrica por columna

Cada columna de salida es su propia agregación, así que puedes combinarlas: sesiones y páginas vistas por dispositivo, o pedidos e ingresos por canal.

Contar filas por categoría

Para contar en lugar de sumar, suma 1 por cada fila que coincida, o usa COUNT(CASE WHEN ... THEN 1 END): COUNT ignora los NULL que generan las demás filas. Así obtienes tareas por estado o tickets por prioridad.

Convertir filas clave-valor en columnas

Las configuraciones y los atributos de producto suelen guardarse como una fila por nombre y valor. Hacer pivot con MAX(CASE ...) te da una fila por elemento con una columna por atributo. MAX funciona con texto y toma el único valor de cada grupo.

Ejemplos reales de tablas dinámicas en SQL

Calificación promedio de apps por plataforma

Omite el ELSE cuando calcules promedios, para que una app sin reseñas en una plataforma muestre NULL en lugar de una calificación engañosa:

-- Input: reviews
-- app      | platform | rating
-- ---------+----------+-------
-- Budgetly | iOS      | 5
-- Budgetly | iOS      | 4
-- Budgetly | Android  | 3
-- FitTrack | Android  | 4
-- FitTrack | Android  | 5

-- In SQL Server, AVG of an integer column drops the decimals: use rating * 1.0
SELECT
  app,
  ROUND(AVG(CASE WHEN platform = 'iOS' THEN rating END), 1) AS ios,
  ROUND(AVG(CASE WHEN platform = 'Android' THEN rating END), 1) AS android
FROM reviews
GROUP BY app
ORDER BY app;

-- Output:
-- app      | ios  | android
-- ---------+------+--------
-- Budgetly | 4.5  | 3.0
-- FitTrack | NULL | 4.5

Pedidos y ventas por canal en cada región

Dos métricas por canal, un conteo de pedidos y un total:

-- Input: orders
-- id | region | channel | amount
-- ---+--------+---------+-------
-- 1  | North  | web     | 120.00
-- 2  | North  | store   | 80.00
-- 3  | North  | web     | 45.50
-- 4  | South  | store   | 210.00
-- 5  | South  | store   | 64.00

SELECT
  region,
  COUNT(CASE WHEN channel = 'web' THEN 1 END) AS web_orders,
  SUM(CASE WHEN channel = 'web' THEN amount ELSE 0 END) AS web_sales,
  COUNT(CASE WHEN channel = 'store' THEN 1 END) AS store_orders,
  SUM(CASE WHEN channel = 'store' THEN amount ELSE 0 END) AS store_sales
FROM orders
GROUP BY region
ORDER BY region;

-- Output:
-- region | web_orders | web_sales | store_orders | store_sales
-- -------+------------+-----------+--------------+------------
-- North  | 2          | 165.50    | 1            | 80.00
-- South  | 0          | 0         | 2            | 274.00

Tickets de soporte por agente según prioridad

Un conteo por prioridad, más un total. COUNT(*) sigue contando todas las filas del grupo:

-- Input: tickets
-- id | agent | priority
-- ---+-------+---------
-- 1  | Priya | urgent
-- 2  | Priya | normal
-- 3  | Marco | normal
-- 4  | Priya | normal
-- 5  | Marco | low

SELECT
  agent,
  COUNT(CASE WHEN priority = 'low' THEN 1 END) AS low,
  COUNT(CASE WHEN priority = 'normal' THEN 1 END) AS normal,
  COUNT(CASE WHEN priority = 'urgent' THEN 1 END) AS urgent,
  COUNT(*) AS total
FROM tickets
GROUP BY agent
ORDER BY agent;

-- Output:
-- agent | low | normal | urgent | total
-- ------+-----+--------+--------+------
-- Marco | 1   | 1      | 0      | 2
-- Priya | 0   | 2      | 1      | 3

Una fila de configuración por usuario

Cada configuración se guarda como un nombre y un valor. Un usuario que nunca definió una obtiene NULL en esa columna:

-- Input: user_settings
-- user_id | setting  | value
-- --------+----------+--------------
-- 1       | theme    | dark
-- 1       | language | en
-- 2       | language | de
-- 2       | timezone | Europe/Berlin
-- 3       | theme    | light

SELECT
  user_id,
  MAX(CASE WHEN setting = 'theme' THEN value END) AS theme,
  MAX(CASE WHEN setting = 'language' THEN value END) AS language,
  MAX(CASE WHEN setting = 'timezone' THEN value END) AS timezone
FROM user_settings
GROUP BY user_id
ORDER BY user_id;

-- Output:
-- user_id | theme | language | timezone
-- --------+-------+----------+--------------
-- 1       | dark  | en       | NULL
-- 2       | NULL  | de       | Europe/Berlin
-- 3       | light | NULL     | NULL

Más lecturas sobre tablas dinámicas

En este blog:

Documentación oficial:

Beekeeper Studio es un cliente de bases de datos gratuito y de código abierto

La mejor herramienta de consultas y edición de SQL que he usado. Tiene todo lo que necesito para administrar mi base de datos. - ⭐⭐⭐⭐⭐ Mit

Beekeeper Studio es rápido, intuitivo y fácil de usar. Es compatible con muchísimas bases de datos y funciona de maravilla en Windows, Mac y Linux.

La versión de Beekeeper para Linux tiene el 100% de las funciones, sin recortes ni concesiones.

Lo que dicen los usuarios de Beekeeper Studio

★★★★★
"Beekeeper Studio reemplazó por completo mi antiguo flujo de trabajo con SQL. Es rápido, intuitivo y hace que trabajar con bases de datos vuelva a ser agradable."
— Alex K., desarrollador de bases de datos
★★★★★
"He probado muchas GUI de bases de datos, pero Beekeeper logra el equilibrio perfecto entre funciones y sencillez. Simplemente funciona."
— Sarah M., ingeniera full stack

¿Listo para mejorar tu flujo de trabajo con SQL?

download Descarga gratis