Tabla de Contenidos
Snippets MySQL
Colección de consultas u operaciones útiles o interesantes de MySQL.
Filtrar con expresiones regulares
Buscar registros cuyo campo campo1 comience un numero:
SELECT * FROM tabla WHERE campo1 regexp '^[0-9]+'
Buscar registros cuyo campo campo1 comience por alguno de los números indicados:
SELECT * FROM tabla WHERE campo1 regexp '^(15001|15002)+'
Agrupar
Agrupar por un valor y concatenar los demás en una columna
Por ejemplo, si tenemos:
| servicio_web | |
|---|---|
| 11111 | mail@mail.com |
| 22222 | mail@mail.com |
| 33333 | mail@mail.com |
| 44444 | mail@mail.com |
Y queremos obtener el siguiente resultado:
| servicio_web | |
|---|---|
| mail@mail.com | 11111, 22222, 33333, 44444 |
Usaremos la función GROUP_CONCAT:
SELECT email, GROUP_CONCAT(servicio_web ORDER BY servicio_web ASC SEPARATOR ', ') FROM mitabla GROUP BY email
Búsqueda de valores duplicados
Si queremos ver qué valores están duplicados en cierto campo, podemos hacer la siguiente consulta:
SELECT campo1, COUNT(*) c FROM mitabla GROUP BY campo1 HAVING c > 1
Nos devolverá los valores de campo1 que se repiten (de 1 a más veces)
- Finding duplicate values in MySQL (Stack Overflow)
Fechas
Conversiones
Pasar de marca de tiempo UNIX a formato ISO:
SELECT FROM_UNIXTIME(fecha) as fecha_iso
Salida:
fecha_iso --------- 2020-08-12 00:35:40
El tiempo UNIX (Epoch Time) es el número de segundos transcurridos desde el 01/01/1970 (UTC). Por ejemplo, las 10:00 del 01/08/2020 UTC, serían 1596276000 en tiempo UNIX.
Para convertir una fecha en tiempo UNIX:
SELECT UNIX_TIMESTAMP('2020-08-01 10:00')
Para convertir UTC en cierta zona horaria:
SELECT CONVERT_TZ(fecha_en_utc, 'UTC', 'Europe/Madrid') AS fecha_madrid FROM tabla
Convertir segundos a formato de tiempo (tipo de dato TIME):
SELECT SEC_TO_TIME(3600) -- Devolverá '01:00:00'
Convertir un string a tipo fecha:
SELECT str_to_date('12/12/2022 9:04:12', '%d/%m/%Y %k:%i:%s')
Si partimos de un string como 6/25/2024 2:25:42 AM, para pasarlo a formato fecha:
SELECT str_to_date('6/25/2024 2:25:42 AM', '%c/%e/%Y %l:%i:%s %p')
%c: número del mes sin cero inicial (del 1 al 12)%e: número del día del mes sin cero inicial (del 1 al 31)%Y: número del año%l: hora sin cero inicial (de 1 a 12)%i: minutos (de 00 a 59)%s: segundos (de 00 a 59)%p: AM o PM.
Documentación oficial de formateadores de fecha admitidos en MySQL
Otros
Fecha de hoy:
SELECT CURDATE()
También se puede utilizar la función CURRENT_DATE
Fecha de ayer:
SELECT SUBDATE(CURRENT_DATE, 1)
Hace dos semanas:
select DATE_SUB(curdate(), INTERVAL 2 WEEK)
Lunes de la semana actual:
SELECT DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) as fecha
Lunes de la semana pasada:
SELECT DATE_SUB(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 7 DAY) AS fecha
Agrupar por semanas:
SELECT fecha, DATE_FORMAT(fecha, "%x-%v") AS ano_semana FROM tabla GROUP BY ano_semana ORDER BY fecha
%x: año de la semana donde el lunes es el primer día de la semana. Se usa con%v.%v: número de la semana (de 01 a 53) donde el lunes es el primer día de la semana. Se usa con%x.
Si se usa WEEK, hay un problema con la última semana y primera del año. Si no es una semana completa, crea dos registros: una semana con los últimos días del año y otra semana con los primeros días del año siguiente. Más información sobre la ISO 8601.
Operaciones
Sumar/restart tiempo:
-- Añadir 1 día a la fecha SELECT DATE_ADD(fecha, INTERVAL 1 DAY) -- Restar 1 día a la fecha SELECT DATE_SUB(fecha, INTERVAL 1 DAY)
Para restar tiempo de una expresión de tiempo o fecha+tiempo:
SELECT SUBTIME('12:35:00', '1:30:00'); // 11:05:00
Para ordenar, dejando los valores NULL al final:
SELECT * FROM mitabla WHERE ... ORDER BY CASE WHEN mifecha IS NULL THEN 1 ELSE 0 END, mifecha
Diferencia entre fechas:
SELECT TIMEDIFF(fecha_fin, fecha_inicio) FROM mitabla -- fecha_fin: 2021-03-30 09:09:40 -- fecha_inicio: 2021-03-30 08:30:01 -- TIMEDIFF = 00:39:39
Diferencia en horas:
SELECT TIMESTAMPDIFF(HOUR, fecha_inicio, fecha_fin) FROM mitabla
Comparaciones
Registros de hace más de una hora:
SELECT * FROM tabla WHERE fecha_registro < DATE_SUB(NOW(), INTERVAL '1' HOUR)
Idioma
Fechas
Para que el nombre del día, mes y sus abreviaturas aparezcan en cierto idioma:
SET lc_time_names = 'es_ES'
SELECT DATE_FORMAT(fecha, '%b') as mes_abreviado FROM tabla
Salida:
mes_abreviado ------------- nov abr may jun dic
El cambio durará hasta que finalice la sesión.
Si queremos ver el valor actual de esa variable:
SELECT @@lc_time_names;
Extracción de texto
Extraer una dirección de e-mail de un campo de texto:
SELECT REGEXP_SUBSTR(campo_texto, '([a-zA-Z0-9._%+\-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,4})') AS email FROM tabla
Eliminar saltos de línea
Si tenemos algún campo con saltos de línea (\n en sistemas UNIX y \r\n en Windows), podemos borrarlos con:
UPDATE test SET log = REPLACE(REPLACE(log, '\r', ''), '\n', '');
Concatenar campos que pueden ser NULL
Si usamos la función CONCAT y algún campo puede tener valor NULL, la función devolverá NULL. Si este no es el comportamiento que queremos, debemos usar CONCAT_WS cuyo primer argumento es el separador:
SELECT CONCAT_WS(" ", campo1, campo2, campo3_que_puede_tener_null, campo4) FROM tabla
CONCAT_WS viene de Concatenate With Separator.
Sistema
Tamaño bases de datos
SELECT table_schema "Base de datos", ROUND(SUM(data_length + index_length) / 1024 / 1024, 1) "Tamaño (MB)" FROM information_schema.tables GROUP BY table_schema
Usuarios
Crear usuario
Dar permisos
GRANT ALL PRIVILEGES ON base_datos.tabla TO 'newuser'@'localhost'; FLUSH PRIVILEGES;
Mostrar usuarios
Modificaciones
Último ID insertado
Si hacemos una inserción/modificación en una tabla donde una columna tiene el atributo AUTO_INCREMENT, podemos utilizar la función mysqli_insert_id() para obtener el ID generado por la consulta de inserción/modificación:
(...) $query = "INSERT INTO myCity VALUES (NULL, 'Stuttgart', 'DEU', 'Stuttgart', 617000)"; mysqli_query($link, $query); printf ("Nuevo registro con el id %d.\n", mysqli_insert_id($link));
Modificar valor inicial AUTO_INCREMENT
Si queremos establecer un valor para la clave que contiene AUTO_INCREMENT:
ALTER TABLE mitabla AUTO_INCREMENT=1001;
En las próximas inserciones, la columna con AUTO_INCREMENT se rellenará desde 1001 y siguientes.
Insertar varios registros a la vez
Tablas
Duplicar tabla
Para duplicar una tabla a partir de otra (conservando índices y estructura) se hace en dos consultas pasos: primero haremos crearemos una tabla a partir de la que nos interesa copiar:
CREATE TABLE tabla_copia LIKE tabla_origen
Y ahora añadimos todo lo que había en la tabla origen a su copia:
INSERT INTO tabla_copia SELECT * FROM tabla_origen
Modificar una tabla con valores de otra tabla
UPDATE tabla_a_actualizar INNER JOIN tabla_de_la_que_copiar ON (tabla_a_actualizar.valor = tabla_de_la_que_copiar.valor) SET tabla_a_actualizar.campo1 = tabla_de_la_que_copiar.campo1
- Update one MySQL table with values from another (Stack Overflow)
Listar tablas de una base de datos
Eliminar tabla
DROP TABLE IF EXISTS <NOMBRE_TABLA>
Si queremos eliminar más de una a la vez:
DROP TABLE IF EXISTS <TABLA1>, <TABLA2>, <TABLA3>
Obtener nombre columnas
Para ver el listado de campos de una tabla y su tipo:
DESCRIBE <NOMBRE_TABLA>
Si queremos obtener el listado de campos separados por coma:
-- Aumentamos la longitud máxima de 'group_concat' (por defecto, 1024 caracteres) -- Esto solo se mantiene durante la sesión SET SESSION group_concat_max_len = 1000000; SELECT group_concat(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '<BASE_DATOS>' AND TABLE_NAME = '<NOMBRE_TABLA>';
Administración
Mostrar lista de procesos
show full processlist;
Ejemplo de salida:
+---------+-----------+-------------------+-----------------------+---------+------+-------+-----------------------+ | Id | User | Host | db | Command | Time | State | Info | +---------+-----------+-------------------+-----------------------+---------+------+-------+-----------------------+ | 1195431 | postventa | 10.0.42.185:52702 | tiempos_provision_krt | Sleep | 3559 | | NULL | | 1195818 | postventa | localhost | NULL | Query | 0 | init | show full processlist | +---------+-----------+-------------------+-----------------------+---------+------+-------+-----------------------+
Detener un proceso
Primero buscamos los procesos en ejecución:
SHOW PROCESSLIST;
Y luego, cuando tengamos identificada la ID del proceso que nos interesa, lo detenemos:
KILL <ID_PROCESO>
Eventos
Crear
Ejemplo de evento que elimina registros distintos de la fecha actual diariamente a las 00:01:
CREATE EVENT `eliminar_antiguas_tabla_incidencias_hoy` ON SCHEDULE EVERY 1 DAY STARTS (TIMESTAMP(CURRENT_DATE) + INTERVAL 1 DAY + INTERVAL 1 MINUTE) ON COMPLETION PRESERVE ENABLE COMMENT 'Elimina incidencias antiguas de la tabla que guarda incidencias del día en curso' DO DELETE FROM qep_tbook.incidencias_hoy WHERE DATE_FORMAT(fecha_creacion, '%Y-%m-%d') <> CURDATE()
Mostrar
Todos los eventos:
SHOW EVENTS;
Deshabilitar
Eliminar
DROP EVENT <NOMBRE_EVENTO>
Última ejecución
Mostrar los eventos y la última vez que se ejecutaron:
SELECT EVENT_NAME, INTERVAL_VALUE, INTERVAL_FIELD, LAST_EXECUTED FROM INFORMATION_SCHEMA.events
