Curso de MySQL

Consulta de datos con SELECT en MySQL: guía completa

Por Víctor Peña · Publicado el

Consulta de datos utilizando la cláusula SELECT

Hola, ¿cómo están? Continuando con el curso de MySQL, llegamos a la sentencia más usada de todas: SELECT.

Hasta ahora escribimos datos. A partir de aquí los leemos, que es el 90 % de lo que hace cualquier aplicación.

¡Empecemos!

La consulta más simple

SELECT * FROM pacientes;

El asterisco significa «todas las columnas».

Es cómodo para explorar, pero no lo uses en tus aplicaciones. Trae columnas que no necesitas, y el día que alguien agregue una columna TEXT pesada, tus consultas se vuelven lentas sin que hayas tocado nada.

Lo correcto es pedir solo lo que vas a usar:

SELECT nombre, apellido, telefono FROM pacientes;

Filtrar con WHERE

SELECT nombre, apellido, fecha_nacimiento
FROM pacientes
WHERE fecha_nacimiento > '2000-01-01';

WHERE es donde ocurre lo interesante, y lo veremos en detalle en la siguiente lección. Por ahora, los básicos:

WHERE estado = 'programada'
WHERE costo > 200
WHERE fecha BETWEEN '2026-04-01' AND '2026-04-30'
WHERE telefono IS NULL
WHERE estado IN ('programada', 'atendida')

Cuidado con NULL

Aquí hay una trampa que sorprende a todo el mundo:

SELECT * FROM pacientes WHERE telefono = NULL;   -- no devuelve nada
SELECT * FROM pacientes WHERE telefono IS NULL;  -- correcto

NULL significa «desconocido», y nada es igual a lo desconocido, ni siquiera otro desconocido. Por eso = NULL nunca es verdadero.

Usa siempre IS NULL e IS NOT NULL.

Ordenar con ORDER BY

SELECT nombre, apellido FROM pacientes
ORDER BY apellido ASC;

SELECT fecha, costo FROM citas
ORDER BY fecha DESC, hora ASC;

ASC es ascendente y es el valor por defecto; DESC descendente.

Puedes ordenar por varias columnas: en el ejemplo, primero por fecha de más reciente a más antigua, y dentro de cada fecha por hora.

Sin ORDER BY, el orden no está garantizado. Puede parecer que salen ordenadas por id, pero MySQL no lo promete. Si el orden importa, decláralo.

Limitar resultados con LIMIT

SELECT * FROM citas ORDER BY fecha DESC LIMIT 10;

Las 10 más recientes. Y para paginar:

SELECT * FROM citas ORDER BY fecha DESC LIMIT 10 OFFSET 20;

Salta 20 filas y devuelve las 10 siguientes: la tercera página.

Un aviso sobre OFFSET grande: LIMIT 10 OFFSET 100000 obliga a MySQL a recorrer cien mil filas para descartarlas. En tablas grandes se vuelve lentísimo. La alternativa es paginar por el último id visto:

SELECT * FROM citas WHERE id > 100000 ORDER BY id LIMIT 10;

Alias con AS

Renombrar columnas en el resultado:

SELECT
    nombre AS nombre_paciente,
    apellido AS apellido_paciente,
    costo * 1.13 AS total_con_impuesto
FROM citas;

Los alias son imprescindibles cuando calculas algo: sin AS, la columna se llamaría costo * 1.13.

También se usan para las tablas, y ahí se agradecen mucho:

SELECT c.fecha, c.costo
FROM citas AS c
WHERE c.estado = 'programada';

El AS es opcional —FROM citas c funciona igual— y es lo que verás en la mayoría del código.

Eliminar duplicados con DISTINCT

SELECT DISTINCT estado FROM citas;

Devuelve cada estado una sola vez. Útil para saber qué valores existen en una columna.

Con varias columnas, considera la combinación completa como única:

SELECT DISTINCT paciente_id, doctor_id FROM citas;

Concatenar y dar formato

SELECT
    CONCAT(nombre, ' ', apellido) AS nombre_completo,
    UPPER(apellido) AS apellido_mayus,
    DATE_FORMAT(fecha_nacimiento, '%d/%m/%Y') AS nacimiento
FROM pacientes;

Funciones que vas a usar seguido:

Función Qué hace
CONCAT() Une textos
UPPER() / LOWER() Mayúsculas / minúsculas
TRIM() Quita espacios sobrantes
SUBSTRING() Extrae parte de un texto
LENGTH() Longitud
ROUND() Redondea
DATE_FORMAT() Da formato a una fecha
TIMESTAMPDIFF() Diferencia entre fechas

Calcular la edad, por ejemplo:

SELECT
    nombre,
    TIMESTAMPDIFF(YEAR, fecha_nacimiento, CURDATE()) AS edad
FROM pacientes;

Condiciones dentro del SELECT

CASE permite devolver valores distintos según la fila:

SELECT
    nombre,
    costo,
    CASE
        WHEN costo >= 300 THEN 'Alto'
        WHEN costo >= 200 THEN 'Medio'
        ELSE 'Bajo'
    END AS rango_costo
FROM citas;

Y IF() para casos simples de dos opciones:

SELECT nombre, IF(telefono IS NULL, 'Sin teléfono', telefono) AS contacto
FROM pacientes;

Existe también IFNULL(), específica para eso:

SELECT nombre, IFNULL(telefono, 'Sin teléfono') AS contacto FROM pacientes;

El orden de ejecución

Este concepto explica muchos errores, así que vale la pena entenderlo.

El orden en que escribes una consulta:

SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT

El orden en que MySQL la ejecuta es distinto:

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT

Fíjate en que SELECT se ejecuta casi al final. De ahí se deriva algo práctico:

-- Falla: el alias todavía no existe cuando se evalúa el WHERE
SELECT costo * 1.13 AS total FROM citas WHERE total > 300;

-- Funciona: ORDER BY sí se ejecuta después del SELECT
SELECT costo * 1.13 AS total FROM citas ORDER BY total DESC;

Puedes usar un alias en ORDER BY pero no en WHERE. Ahora sabes por qué.

Consultas sobre nuestro sistema

Con los datos que insertamos, prueba estas:

-- Pacientes ordenados por apellido
SELECT nombre, apellido, telefono
FROM pacientes
ORDER BY apellido;

-- Citas de abril, de la más cara a la más barata
SELECT fecha, hora, costo, estado
FROM citas
WHERE fecha BETWEEN '2026-04-01' AND '2026-04-30'
ORDER BY costo DESC;

-- Las tres citas más próximas que siguen programadas
SELECT fecha, hora, costo
FROM citas
WHERE estado = 'programada' AND fecha >= CURDATE()
ORDER BY fecha, hora
LIMIT 3;

-- Pacientes menores de edad
SELECT
    CONCAT(nombre, ' ', apellido) AS paciente,
    TIMESTAMPDIFF(YEAR, fecha_nacimiento, CURDATE()) AS edad
FROM pacientes
WHERE TIMESTAMPDIFF(YEAR, fecha_nacimiento, CURDATE()) < 18;

Buenas prácticas

  • Nombra las columnas, no uses SELECT * en producción.
  • LIMIT al explorar una tabla que no conoces. Un SELECT * sobre millones de filas puede colgar la herramienta.
  • ORDER BY explícito si el orden importa.
  • IS NULL, nunca = NULL.
  • Alias claros en columnas calculadas.

Errores comunes

  • WHERE telefono = NULL.
  • Usar un alias del SELECT dentro del WHERE.
  • Asumir un orden sin ORDER BY.
  • SELECT * en una aplicación, trayendo columnas pesadas sin necesidad.
  • OFFSET enorme para paginar tablas grandes.

Para cerrar

SELECT es la sentencia que más vas a escribir en tu vida como desarrollador. Lo básico se aprende en una tarde; lo que marca diferencia es entender el orden de ejecución y el comportamiento de NULL.

En la siguiente lección profundizamos en los operadores del WHERE, que es donde una consulta se vuelve precisa.

Saludos y éxitos.

Norvic Software

Desarrollamos el software que tu empresa necesita

Somos una fábrica de software en Bolivia. Construimos sistemas a medida y aplicaciones móviles, y llevamos Inteligencia Artificial a las empresas que ya tienen un sistema funcionando.

Solicitar cotizaciónVer todos los servicios

Cotización sin costo · Respuesta directa por WhatsApp