Ver Mensaje Individual
  #2 (permalink)  
Antiguo 27/05/2011, 03:03
quimfv
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 1 mes
Puntos: 574
Respuesta: restar campos pareados de una tabla, y sumar sus resultados

Código MySQL:
Ver original
  1. SELECT elemento,
  2.              sum(if(evento="entrada",valor,0)) as Entradas,
  3.              sum(if(evento="salida",valor,0)) as Salidas,
  4.             sum(if(evento="salida",valor,0))-sum(if(evento="entrada",valor,0)) as dif
  5. FROM eventos
  6. GROUP BY elemento;

elemento...Entradas...Salidas...dif
1............... 1200.........2450......1250
2..................230...........530........300
3................1450...........500.......-950
4..................800...........850..........50

El resultado para el elemento 1 es correcto!?!

Creo que por la propiedad asociativa de la suma el resultado debe ser bueno...

+(E1-S1)+(E2-S2)=+E1-S1+E2-S2=+E1+E2-S1-S2=(E1+E2)-(S1+S2)=SUMA(E1,E2)-SUMA(S1,S2)

Es decir no hace falta aparear los valores...No se si me explico...

No se como deben jugar las entradas sin salida... haciendolo como te propongo actuará así

+(E1-S1)+(E2-0)=...=SUMA(E1,E2)-S1

en el caso que la entrada E2 no tenga su correspondiente S2...

Asociatividad (álgebra)

Parece por tu ejemplo que quieres eliminar las entradas que no tengan salida.... dejame pensar un rato.

Se trataria de elmimiar el ultimo evento de los elementos que tengan un numero impar de eventos....


Código MySQL:
Ver original
  1. SELECT eventos.elemento
  2. FROM eventos
  3. GROUP BY eventos.elemento
  4. HAVING Count(*) Mod 2<>0;

Esto nos da el elmento 3, el unico que no tiene los eventos apareados...

Ahora se tratari de encontarar los ultimos eventos de los elementos obtenido con la consulta anterior.... (como id es autoincremental MAX(fecha) y MAX(id) retornan el mismo registro) luego...

Código MySQL:
Ver original
  1. SELECT Max(eventos.id) AS MxId
  2.         FROM eventos
  3.         GROUP BY eventos.elemento
  4.         HAVING eventos.elemento In (SELECT eventos.elemento
  5.                                                             FROM eventos
  6.                                                             GROUP BY eventos.elemento
  7.                                                             HAVING Count(*) Mod 2<>0);

esto nos da el evento 8, precisamente el que buscabamos....

Ya llegamos!!!

Ahora hay que usar esto para que la primera consulta solo tenga encuenta los eventos que NO estan en esta ultima


Código MySQL:
Ver original
  1. SELECT eventos.elemento,
  2.              Sum(If(evento="entrada",valor,0)) AS Entradas,
  3.              Sum(If(evento="salida",valor,0)) AS Salidas,
  4.              Sum(If(evento="salida",valor,0))-Sum(If(evento="entrada",valor,0)) AS dif
  5. FROM eventos
  6. WHERE eventos.id
  7.      Not In (SELECT Max(eventos.id) AS MxId
  8.                  FROM eventos
  9.                  GROUP BY eventos.elemento
  10.                  HAVING eventos.elemento
  11.                         In (SELECT eventos.elemento
  12.                              FROM eventos
  13.                              GROUP BY eventos.elemento
  14.                              HAVING Count(*) Mod 2<>0))
  15. GROUP BY eventos.elemento;

Puede que tengas que jugar con los alias pero esto da:

elemento...Entradas...Salidas...dif
1............... 1200.........2450......1250
2..................230...........530........300
3..................450...........500..........50
4..................800...........850..........50

!!!

Funcionará siempre que la secuencia temporal sea coherente, es decir que no haya ningun elemento con dos entradas seguidas y que no tengan salida... esto deberias controlarlo antes. Si no fuera el caso habria que buscar otra solución.
__________________
Quim
--------------------------------------------------
Ayudar a ayudar es una buena práctica!!! Y da buenos resultados.

Última edición por quimfv; 27/05/2011 a las 05:23