Ver Mensaje Individual
  #12 (permalink)  
Antiguo 01/08/2011, 10:02
Avatar de gnzsoloyo
gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: Operacion con campo anterior de una columna



...Si. es una sintaxis algo complicada porque requiere conocer las subconsultas y tener cierto dominio sobre las variables de usuario en MySQL...

El tema es así:
Las variables de usuario son variables que se crean en una conexión establecida por un usuario y que tienen algunas características:
- No tienen tipo de dato inicialmente.
- No se las declara; directamente se las crea y usa al invocarlas.
- Se las debe incializar siempre con el tipo de dato a usar.
- Cuando no se las incializa su valor es NULL, por lo que cualquier operación con ellas dará NULL.
- Existen sólo en la conexión, lo que significa que dejan de existir al cerrarse esta.
- Como dependen de la conexión, y sólo existen en ella, dos conexiones diferentes pueden usar el mismo nombre de variable, porque se refieren a objetos diferentes. No hay conflictos. Incluso si las conexiones son abiertas por el mismo usuario, las variables pueden usar el mismo nombre y contener cosas diferentes.
- Toman su valor dinámicamente, por lo que si en una operación vas asignando valores distintos a la misma variable, en cada paso tendrá un valor diferente.
- Se les puede asignar un valor dinámicamente en una consulta con ayuda de ":=". Eso permite variar el valor en cada registro y columna leídos.
- Conservan su último valor, por lo que cada vez que se las usa se deben reinicializar.

Esto te puede dar un ejemplo:
Código MySQL:
Ver original
  1. mysql> SELECT @A;
  2. +------+
  3. | @A   |
  4. +------+
  5. | NULL |
  6. +------+
  7. 1 row in set (0.00 sec)
  8.  
  9. mysql> SELECT @A:=0, @A, @A:=33, @A, @A:=@A -344, @A, @A:=1, @A;
  10. +-------+------+--------+------+-------------+------+-------+------+
  11. | @A:=0 | @A   | @A:=33 | @A   | @A:=@A -344 | @A   | @A:=1 | @A   |
  12. +-------+------+--------+------+-------------+------+-------+------+
  13. |     0 | 0    |     33 | 33   |        -311 | -311 |     1 | 1    |
  14. +-------+------+--------+------+-------------+------+-------+------+
  15. 1 row in set (0.00 sec)
  16.  
  17. mysql> SELECT @A;
  18. +------+
  19. | @A   |
  20. +------+
  21. | 1    |
  22. +------+
  23. 1 row in set (0.00 sec)

Ahora veamos la consulta por partes:
1) Creando la variable.
El único objetivo de esta parte es crear la variable, incializarla y dejarla disponible para la subconsulta, sin necesidad de ejecutar una consulta previa para eso:
Código MySQL:
Ver original
  1. (SELECT @kml:=0)

2) Creando la suma y cálculos:
Código MySQL:
Ver original
  1. SELECT KM, LITROS, IF(@kml=0, @kml:=KM, @kml)km1, (KM-@kml) RECORRIDO, @kml:= KM
  2.     FROM VALES JOIN (SELECT @kml:=0) T1
Es la que hace casi todo el trabajo:
1) Toma el valor de KM y LITROS.
2) Luego, si el valor de @kml es cero significa que es el primer registro, entonces le asigna el valor de KM a @kml, sino simplemente reproduce el último valor tomado (tiene que hacer algo).
3) Luego calcula la resta entre el valor de KM actual y el último valor tomado de @kml y le da el nombre de "RECORRIDO".
4) Asigna el valor actual de KM a @kml.
Esto devuelve una tabla que contiene: KM, LITROS, @kml anterior, RECORRIDO (parcial) y @kml actualizado.

Con estos datos, la consulta exterior simplemente hace:
1) Agrupa haciendo un ROLLUP sobre KM, sumando todos los parciales de litros y recorrido. Esto devolverá un registro por cada KM distinto, más un registro final con la suma total y NULL en todos los campos que no estén en el GROUP BY.
2) Si KM es NULL, significa que es el último renglón, entonces reemplaza el NULL por "Total en la primera columna y un vacío en la segunda.

¿Se entiende la idea?
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)