Estrategia: ir hacia adelante
El Software Libre siempre está en desarrollo, aunque esté acabado, hay muy pocos productos que se estanquen en versiones finales.
Podemos decir: si esta versión que uso era buena cuando la instalé, ¿por qué cambiar? Pues puedo aportar mi expericia personal, y uno de los paquetes que más problemas me han causado por trabajar con versiones poco actuales es MySQL.
La gente se suele sorprender, ¿MySQL
no siempre ha tenido subconsultas? Pues no señores, antes de la versión 4.1 no hay. Y vaya si complica las cosas :(.
Esta semana mismo he tenido que hacer una consulta algo más compleja de la cuenta, y me he visto atrapado en un MySQL
3.23 que venía en Debian Woody, y sin posibilidades de actualizar.
Voy a simplificar el problema, creo que no es necesario que describa un 20% de la aplicación para entender qué pasaba.
Tengo una serie de etiquetas a las que realizan n lecturas y quiero obtener por cada identificador de etiqueta el tipo de la última lectura. Bien, sencillo... SQL
tiene suficientes recursos para eso:
select b.idEtiqueta, a.tipo from tblLectura as a, tblEtiqueta as b where b.idNota=$nota and b.id=a.idEtiqueta and a.fecha= (select max(fecha) from tblLectura as a2, tblEtiqueta as b2 where b2.idNota=$nota and b2.id=a2.idEtiquetab) order by b.idEtiqueta asc
Fácil, fácil. Hacemos una subconsulta que nos garantice obtener la última lectura por etiqueta, y asunto solucionado. Pero, ¿y si no podemos realizar subconsultas? Bienvenido al infierno :P.
El primer intento es agrupar por etiqueta:
select b.idEtiqueta, a.tipo from tblLectura as a, tblEtiqueta as b where b.idNota=$nota and b.id=a.idEtiqueta group by b.idEtiqueta order by b.idEtiqueta asc
Buen intento, aunque lamentablemente nadie nos garantiza que al agrupar así el tipo que obtengamos sea el que corresponde a la última lectura, ni todo lo contrario. Tenemos un resultado incierto :D.
Afortunadamente la documentación de MySQL
es de primera: The Rows Holding the Group-wise Maximum of a Certain Field.
La solución propuesta para MySQL
4.1 es exáctamente la más lógica (claro, con subconsultas :S), y la que nos da para versiones anteriores consiste en hacer el trabajo en pasos.
Para ello crea una tabla temporal. Este tipo de tablas tienen la particularidad de solo existir para la conexión que las crea y, además, por el tiempo que dura esa conexión.
El resultado es tal que:
-- tabla temporal -- create temporary table tmp(idEtiqueta int, fecha datetime); -- bloqueamos las tablas implicadas para solo lectura -- lock tables tblLectura read, tblEtiqueta read; -- insertamos los máximos (parece un subquery, pero no lo es :D) -- insert into tmp select idEtiqueta, max(fecha) from tblLectura, tblEtiqueta where idNota=$nota and tblEtiqueta.id=idEtiqueta group by idEtiqueta; -- hacemos 'la pregunta' -- select b.idEtiqueta, a.tipo from tblLectura as a, tblEtiqueta as b, tmp as c where b.idNota=$nota and b.id=a.idEtiqueta and a.fecha=c.fecha and a.idEtiqueta=c.idEtiqueta order by b.idEtiqueta asc -- quitamos el bloqueo -- unlock tables; -- limpiamos la casa -- drop table tmp;
Sí, dan escalofríos, aunque en este caso es la solución más cómoda. En otros se puede recurrir a programación del lenguaje donde empleamos SQL
para suplir la falta de subconsultas (como generando listas de claves primarias para usarlas en un where id in($lista)
).
Desde luego MySQL
avanza con pasos firmes. La versión 5.0, de la que saldrá pronto versión para producción, nos trae cosas tan jugosas como:
- Vistas
- Procedimientos y funciones almacenadas
- Disparadores
- Cursores en servidor
Puede ser un poco lioso saber qué funcionalidades tiene o no la versión con la que trabajamos, aunque la primera versión de MySQL
4.1.x apta para producción data ya de Octubre de 2004, con lo que esta situación que he tenido que sufrir cada vez debe ser menos frecuente (en este servidor aún está MySQL
4.0.x, sin subconsultas).
De los problemas de no tener transacciones ni integridad referencial ya hablamos otro día ;).
Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.