MySQL: Calcular una edad a partir de una fecha.

En fin, seguimos con el cálculo de edades a partir de fechas en diferentes SGBD. Ya hablamos de SQL-Server y de PostgreSQL, vamos ahora a ver cómo iría la cosa en MySQL/MariaDB.

Vamos a asumir que los datos están bien guardados, en una columna del tipo DATETIME. Como en el caso de Postgres, en MySQL dispones de una función que nos ayudará a hacer esto directamente, llamada TIMESTAMPDIFF(). Esta función recibe como argumentos la unidad de tiempo en la que queremos recibir la respuesta y las dos fechas entre las que queremos obtener la diferencia. Veamos el ejemplo para obtener la edad de alguien con esta función, sirviéndonos de una tabla de ejemplo llamada clientes que contendrá una columna FechaNac con la fecha de nacimiento de los mismos:

SELECT TIMESTAMPDIFF(YEAR,FechaNac,CURDATE()) AS edad
     FROM clientes;

PostgeSQL: Calcular una edad a partir de una fecha.

No hace mucho veíamos cómo calcular una edad en SQL-Server. Vamos ahora con otro SGBD ¿Cómo lo hago en Postgres? Pues con mucha menos dificultad, porque este gestor incluye ya una función integrada para el cálculo de edades, presente al menos desde la versión 9 (no se si antes) llamada age().

La función puede ser llamada con uno o con dos argumentos, siempre del tipo timestamp, y devuelve el interváluo entre ambos. Para el ejemplo imaginemos una tabla llamada clientes donde tenemos un campo FechaNac con la fecha de nacimiento guardada.

/*Con el primer ejemplo
pasando sólo una fecha
cogería la edad a día de hoy
de alguien nacido en esa fecha*/
Select age(timestamp FechaNac) from clientes

/*Con el segundo ejemplo
pasando dos fechas
cogería la edad que una
persona nacida en la fecha 2
tenía en la fecha 1*/

Select age(timestamp '2014-01-01',timestamp FechaNac) from clientes

CSS3 Media Queries para Moto 360 Watch

Si el otro día os comentaba que había estado ojeando el tema de las media queries para los dispositivos de Apple, vamos ahora con el wearable de Motorola. ¿Qué resulución usaría en CSS para este dispositivo? Pues esta:

@media 
  (max-device-width: 218px)
  and (max-device-height: 281px) { 
/*Aquí lo que toque*/
}

Conforme me vaya enterando de más dispositivos los iré compartiendo por aquí.

SQL Server: Calcular una edad a partir de una fecha.

¿Cuántas veces no tenemos que sacar, en una consulta, la edad de una persona a partir de su fecha de nacimiento? Es una consulta que me toca hacer habitualmente (y que, mira por dónde, nunca había comentado aquí). ¿Cómo lo hacemos en SQL-Server?

Pensemos que tenemos una tabla clientes, donde hay un campo de tipo DATE llamado FechaNac en el que almacenamos sus fechas de nacimiento. Podrías creer que lo más simple es hacer lo siguiente:

Select DATEDIFF(YEAR,FechaNac,GETDATE()) as Edad from clientes

Pero hay un problema: Esa solución sólo resta los años, no tiene en cuenta el mes y el día ¿qué pasaría entonces? Que nos pondría la edad que ese cliente va a cumplir durante este año, no su edad real. ¿Cómo lo solucionamos? Hay muchas opciones, yo he optado por esta:

Select DATEDIFF(YEAR,FechaNac,GETDATE())
-(CASE
   WHEN DATEADD(YY,DATEDIFF(YEAR,clientes.FechaNac,GETDATE()),clientesFechaNac)>GETDATE() THEN 
      1
   ELSE 
      0 
   END) as Edad
 from clientes

Lo que hacemos es sumar la diferencia de años a la fecha de nacimiento y, en caso de que fuera posterior a hoy (es decir, todavía no ha cumpliado años) restamos 1 a la diferencia, si no restamos 0 y nos quedamos como estamos.

Otra opción, más elegante, podría ser esta:

Select floor(
(cast(convert(varchar(8),getdate(),112) as int)-
cast(convert(varchar(8),clientes.FechaNac,112) as int) ) / 10000
) as edad from clientes

En este caso convertimos la fecha al formato clásico de base de datos como una cadena que aglutina pegados Fecha, mes y día y lo convertimos a un entero (hoy nos quedaría por ejemplo 20151001), se lo restamos a la fecha de nacimiento, dividimos entre diez mil para obtener el año y redondeamos por defecto con la función floor().

Media Queries para Apple Watch

Minientrada sobre CSS (y maquera muy a mi pesar) rápida mientras cocino una más musical para esta semana. ¿Cuál sería el tamaño de pantalla en una media query para aplicar un estilo CSS concreto a algo que se visualice en un dispositivo Apple Watch (aka El Reloj Manzanita)? Pues segú veo en github sería lo siguiente:

@media
  (max-device-width: 42mm)
  and (min-device-width: 38mm) { 
/*Aquí el código css a implementar*/
}

Si me voy enterando de otros dispositivos os los iré anunciando.

Creando una tabla con los bordes redondos con CSS3

¿Cómo puede redondear los bordes de una tabla con CSS? Ponerle bordes al objeto table o al tr no va a funcionar, hay que hacerlo sobre el primer o el último td de la fila.

table { border-collapse: separate; }
td { border: solid 1px #000; }
/*PARA LA PRIMERA FILA TIENES DOS OPCIONES*/
/*Así sería la cosa
si has empezado con un tr
*/
tr:first-child td:first-child { border-top-left-radius: 10px; }
tr:first-child td:last-child { border-top-right-radius: 10px; }
tr:first-child td:only-child { border-top-right-radius: 10px;
border-top-left-radius: 10px; }
/*si en lugar de eso has usado la etiquetas thead y th es más
sencillo todavía*/
th:first-child { border-top-left-radius: 10px; }
th:last-child { border-top-right-radius: 10px; }
th:only-child { border-top-right-radius: 10px;
border-top-left-radius: 10px; }

/*Y ASÍ PONEMOS EL PIE*/
tr:last-child td:first-child { border-bottom-left-radius: 10px; }
tr:last-child td:last-child { border-bottom-right-radius: 10px; }
tr:last-child td:only-child { border-bottom-right-radius: 10px;border-bottom-left-radius: 10px; }

Borrar un evento de MySQL

Hoy me preguntaba en la entrada sobre Eventos en MySQL cómo se borran, así que en vez de contestar en los comentarios voy a dejarlo por aquí en una minientrada general. ¿Cómo se borra un evento? Pues con Drop Event, cuya sintaxis es DROP EVENT [IF EXISTS] event_name. En el viejo ejemplo creábamos uno llamado e_ActualizaSaldoDiario, así que si quisiéramos borrarlo nos bastaría con hacer lo siguiente:

DROP EVENT e_ActualizaSaldoDiario

En caso de que el evento que intentamos borrar no existiera (por haberse borrado previamente) nos devolverá un error. Si queremos evitar esto podemos añadir IF EXISTS:

DROP EVENT IF EXISTS e_ActualizaSaldoDiario

Recordad que para borrarlos, igual que para crearlos, tenéis que tener permisos sobre los eventos en el schema.

Obteniendo un objeto con los datos de un código postal en Google Maps

Van a venir una serie de entradas sobre Google Maps próximamente, y espero que también sobre Open Street Map. Vamos con una simple y cortita ¿cómo podemos obtener un objeto con los datos de un código postal concreto? El API de Google Maps nos permite pedírselos y nos los devuelve en formato XML o JSON.

Vemos dos ejemplos prácticos, el primero nos devuelve el JSON:
http://maps.googleapis.com/maps/api/geocode/json?address=15330&region=ES&sensor=false

Y este es la versión con XML:
http://maps.googleapis.com/maps/api/geocode/xml?address=15330&region=ES&sensor=false

La sintaxis sería la siguiente:

  • Primero la llamada al API de geocodificación de Google Maps: http://maps.googleapis.com/maps/api/geocode/
  • Seguidamente el formato, que puede ser xml o json
  • Como parámetros pasamos en address el código postal, y en region el país (si no buscará en los EEUU por defecto).

En los próximos días seguiremos tratando el tema.

Ultimate Boot CD Live: Creando un usb arrancable y activar la persistencia.

Hoy descubría la existencia de un interesante proyecto ¿Recordais Ultimate Boot Cd? Se trata de un disco de arranque con utilidades muy tipo Hirens Boot Cd. La cuestión es que han sacado una versión de Ultimate Boot CD basado en un LiveCD de Debian, para poder usar las aplicaciones desde entorno gráfico: Ultimate Boot CD Live. Incluye una colección de freeware, shareware y software libre para poder realizar tareas de reparación y recuperación del sistema que puedes ver listas en la página del proyecto.

El proyecto está guay, pero siendo prácticos a día de hoy muchos equipos, sobre todo portátiles, no tienen cd (mismo el caso del equipo desde el que estoy escribiendo) ¿cómo creamos un cd arrancable con Ultimate Boot CD Live? Pues sin mucha dificultad porque,a fin de cuentas, se trata de una distribución Live de Linux como otra cualquiera. En caso de que seais usuarios de Windows os tocará recurrir a opciones como Universal USB Installer o LinuxLive USB Creator. En caso de estar usando Linux, yo suelo ser partidario de Unetbootin. En todo caso los tres son bastante intuitivos, basta con descargar la ISO desde el enlace al proyecto y seleccionarla luego desde el programa que useis para crear el USB. Con LinuxLive USB Creator ya explicamos aquí en su día cómo hacerlo, y con el resto lo podéis encontrar con una simple búsqueda.

Captura de Pantalla de UBCDLive

Ahora vamos con la parte de la persistencia. En caso de que querais guardar cambios en el USB existe una forma de conseguir un giga de espacio para persistencia. Con el cd una vez creado tenéis que buscar el archivo persistence.bz2 y descomprimirlo, de forma que obtendréis un archivo llamado persistence de un giga de tamaño que es en el que se almacenarán los cambios. Además os tocará modificar el archivo isolinux/live.cfg y añadir toram persistence a los parámetros de arranque tal que así:

label live-486
   menu label ^Live (486)
   menu default
   linux /live/vmlinuz
   initrd /live/initrd.img
   append boot=live config username=root vga=normal toram persistence

label live-486-failsafe
   menu label ^Live (486 failsafe)
   linux /live/vmlinuz
   initrd /live/initrd.img
   append boot=live config username=root memtest noapic noapm nodma nomce nolapic nomodeset nosmp nosplash vga=normal toram persistence

Y con esto ya estaría la opción habilitada, y vuestro pendrive listo para ayudaros a rescatar el sistema.

SQL-Server ¿es mejor usar MAX() o TOP 1?

Una duda me asaltaba el otro día preparando una serie de consultas, en una de las cuales tenía que sacar la fecha más alta de una serie de registros. ¿Consumía menos recursos un MAX() o acaso era mejor recurrir a la conjunción de order by y Top 1?

Rebuscando por duckduckgo me encontré con este blog donde disipan la duda:

  1. Si el campo a buscar forma parte de un índice cluster, entonces da igual porque ambas se ejecutan a una velocidad extremadamente rápida
  2. Si el campo a buscar no es un índice cluster entonces MAX() da una respuesta más rápida porque la función está mejor optimizada y tiene menos carga que realizar un order by después del select

En el artículo original están los bancos de pruebas con resultados concretos.