Ver Mensaje Individual
  #3 (permalink)  
Antiguo 02/03/2017, 14:03
leonardo_josue
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 4 meses
Puntos: 447
Respuesta: Obtener y calcular las ultimo dos registros de cada Elemento

Hola gjx2:

Tienes muchas formas de resolver tu consulta, algunas más complejas que otras, aquí te pongo otro ejemplo que puede resultarte más simple.

Lo que quieres hacer sería el equivalente a obtener la función ROW_NUM de tus datos, si tienes dudas investiga un poco a qué se refiere, lamentablemente MySQL no tiene esta función, aunque hay algunas formas de implementarla. Supongamos tus datos de ejemplo:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM tabla;
  2. +------------+-------+---------+
  3. | fecha      | elem  | costo   |
  4. +------------+-------+---------+
  5. | 2017-01-02 | jose  |   32.33 |
  6. | 2017-01-03 | jose  |   11.63 |
  7. | 2017-01-04 | jose  |  484.23 |
  8. | 2017-01-05 | jose  |  292.43 |
  9. | 2017-01-01 | pedro |  532.53 |
  10. | 2017-01-03 | pedro | 2332.00 |
  11. | 2017-01-04 | pedro |  352.13 |
  12. | 2017-01-01 | juan  | 6732.00 |
  13. | 2017-01-03 | juan  |  422.63 |
  14. | 2017-01-05 | juan  |  552.43 |
  15. +------------+-------+---------+
  16. 10 rows in set (0.00 sec)

la función ROW_NUM lo que hace es "numerar" cada registro para asignarle una posición o "rank", una forma de hacerlo es con una subconsulta y con la función COUNT, así:

Código MySQL:
Ver original
  1. mysql> SELECT T1.fecha, T1.elem, T1.costo, COUNT(*) AS row_number
  2.     -> FROM tabla T1
  3.     -> INNER JOIN  tabla t2 ON T1.elem =  T2.elem
  4.     ->                         AND T1.fecha <= T2.fecha
  5.     -> GROUP BY T1.elem, T1.fecha DESC;
  6. +------------+-------+---------+------------+
  7. | fecha      | elem  | costo   | row_number |
  8. +------------+-------+---------+------------+
  9. | 2017-01-05 | jose  |  292.43 |          1 |
  10. | 2017-01-04 | jose  |  484.23 |          2 |
  11. | 2017-01-03 | jose  |   11.63 |          3 |
  12. | 2017-01-02 | jose  |   32.33 |          4 |
  13. | 2017-01-05 | juan  |  552.43 |          1 |
  14. | 2017-01-03 | juan  |  422.63 |          2 |
  15. | 2017-01-01 | juan  | 6732.00 |          3 |
  16. | 2017-01-04 | pedro |  352.13 |          1 |
  17. | 2017-01-03 | pedro | 2332.00 |          2 |
  18. | 2017-01-01 | pedro |  532.53 |          3 |
  19. +------------+-------+---------+------------+
  20. 10 rows in set (0.00 sec)

Lo que se hace es ordenar las por elem y FECHAS, y contar el número de elementos que hay antes que una fecha en específico, en lo particular a ti te interesa encontrar sólo los dos últimos registros, entonces utilizas la cláusula HAVING para filtrar solo los que te interesan;

Código MySQL:
Ver original
  1. mysql> SELECT T1.fecha, T1.elem, T1.costo, COUNT(*) AS row_number
  2.     -> FROM tabla T1
  3.     -> INNER JOIN  tabla t2 ON T1.elem =  T2.elem
  4.     ->                         AND T1.fecha <= T2.fecha
  5.     -> GROUP BY T1.elem, T1.fecha DESC
  6.     -> HAVING COUNT(*) <= 2;
  7. +------------+-------+---------+------------+
  8. | fecha      | elem  | costo   | row_number |
  9. +------------+-------+---------+------------+
  10. | 2017-01-05 | jose  |  292.43 |          1 |
  11. | 2017-01-04 | jose  |  484.23 |          2 |
  12. | 2017-01-05 | juan  |  552.43 |          1 |
  13. | 2017-01-03 | juan  |  422.63 |          2 |
  14. | 2017-01-04 | pedro |  352.13 |          1 |
  15. | 2017-01-03 | pedro | 2332.00 |          2 |
  16. +------------+-------+---------+------------+
  17. 6 rows in set (0.00 sec)

Ahora, esto puedes meterlo en una subconsulta y utilizar las funciones de agrupación MIN, MAX y SUM para obtener el resultado que necesitas:

Código MySQL:
Ver original
  1. mysql> SELECT MIN(fecha) fecha1, MAX(fecha) fecha2, elem, SUM(costo) total
  2.     -> FROM
  3.     -> ( SELECT T1.fecha, T1.elem, T1.costo, COUNT(*) AS row_number
  4.     ->   FROM tabla T1
  5.     ->   INNER JOIN  tabla t2 ON T1.elem =  T2.elem
  6.     ->                           AND T1.fecha <= T2.fecha
  7.     ->   GROUP BY T1.elem, T1.fecha DESC
  8.     ->   HAVING COUNT(*) <= 2 ) T
  9.     -> GROUP BY elem;
  10. +------------+------------+-------+---------+
  11. | fecha1     | fecha2     | elem  | total   |
  12. +------------+------------+-------+---------+
  13. | 2017-01-04 | 2017-01-05 | jose  |  776.66 |
  14. | 2017-01-03 | 2017-01-05 | juan  |  975.06 |
  15. | 2017-01-03 | 2017-01-04 | pedro | 2684.13 |
  16. +------------+------------+-------+---------+
  17. 3 rows in set (0.00 sec)

Es muy importante hacerte notar que esta consulta SÓLO FUNCIONA SI NO TIENES FECHAS REPETIDAS EN TU TABLA PARA UN MISMO ELEMENTO, si fuera el caso, entonces esta técnica no funciona.

Te recomiendo que le des un vistazo a esta página:

http://www.artfulsoftware.com/infotr...ip.php?id=1098

http://www.artfulsoftware.com/infotree/queries.php

Ahí vienen muchas consultas de alto nivel que te pueden servir.

Saludos
Leo.