Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

restar campos pareados de una tabla, y sumar sus resultados

Estas en el tema de restar campos pareados de una tabla, y sumar sus resultados en el foro de Mysql en Foros del Web. Hola, podria alguien ayudarme con lo siguiente por favor: tengo una tabla con los siguientes valores: fecha,valor,evento,elemento 2/2/2011, 1000,'entrada',1 6/7/2011,450,'entrada',3 2/3/2011,2000,'salida',1 4/5/2011,200,'entrada',1 8/8/2011,500,'salida',3 7/6/2011,450,'salida',1 3/1/2011,230,entrada,2 ...
  #1 (permalink)  
Antiguo 21/05/2011, 11:03
 
Fecha de Ingreso: julio-2009
Mensajes: 90
Antigüedad: 15 años, 3 meses
Puntos: 4
Sonrisa restar campos pareados de una tabla, y sumar sus resultados

Hola, podria alguien ayudarme con lo siguiente por favor:

tengo una tabla con los siguientes valores:

fecha,valor,evento,elemento
2/2/2011, 1000,'entrada',1
6/7/2011,450,'entrada',3
2/3/2011,2000,'salida',1
4/5/2011,200,'entrada',1
8/8/2011,500,'salida',3
7/6/2011,450,'salida',1
3/1/2011,230,entrada,2
4/9/2011,1000,'entrada',3
4/3/2011,800,entrada,4
9/4/2011,530,'salida',2
1/5/2011,850,'salida',4


algunas reglas para entender el contexto:

todo evento salida tiene su entrada con una fecha anterior
no todas las entradas tienen una salida aun
siempre el valor de la salida será mayor que la entrada

lo que necesito aqui es poder generar un consulta que me devuelva los restos sumados entre entradas y salidas, por ejemplo debería regresarme:

total,elemento
1250, 1
300,2
50,3
50,4


es decir en el elemento 1 restó 2000 de la salida menos 1000 de la entrada en el primer par y luego restó 450 de la segunda salida menos 200 de la segunda entrada lo que dio 250 y los dos sumados me dan 1250, se entiende?

agrego el sql de los datos para el que quiera echarme una manito


Código MySQL:
Ver original
  1. SET FOREIGN_KEY_CHECKS=0;
  2. -- ----------------------------
  3. -- Table structure for eventos
  4. -- ----------------------------
  5. DROP TABLE IF EXISTS `eventos`;
  6. CREATE TABLE `eventos` (
  7.   `fecha` date NOT NULL,
  8.   `valor` int(11) NOT NULL,
  9.   `evento` varchar(20) COLLATE utf8_spanish_ci NOT NULL,
  10.   `elemento` int(11) NOT NULL,
  11.   PRIMARY KEY (`id`)
  12. ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
  13.  
  14. -- ----------------------------
  15. -- Records
  16. -- ----------------------------
  17. INSERT INTO `eventos` VALUES ('1', '2011-02-02', '1000', 'entrada', '1');
  18. INSERT INTO `eventos` VALUES ('2', '2011-07-06', '450', 'entrada', '3');
  19. INSERT INTO `eventos` VALUES ('3', '2011-03-02', '2000', 'salida', '1');
  20. INSERT INTO `eventos` VALUES ('4', '2011-05-04', '200', 'entrada', '1');
  21. INSERT INTO `eventos` VALUES ('5', '2001-08-08', '500', 'salida', '3');
  22. INSERT INTO `eventos` VALUES ('6', '2011-06-07', '450', 'salida', '1');
  23. INSERT INTO `eventos` VALUES ('7', '2011-01-03', '230', 'entrada', '2');
  24. INSERT INTO `eventos` VALUES ('8', '2011-09-04', '1000', 'entrada', '3');
  25. INSERT INTO `eventos` VALUES ('9', '2011-03-04', '800', 'entrada', '4');
  26. INSERT INTO `eventos` VALUES ('10', '2011-04-09', '530', 'salida', '2');
  27. INSERT INTO `eventos` VALUES ('11', '2011-05-01', '850', 'salida', '4');

cualquier luz será agradecida
__________________
C[^L*]D
[email protected]
tokkaido.blogspot.com
No hay mejor forma de aprender que enseñar
  #2 (permalink)  
Antiguo 27/05/2011, 03:03
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 8 meses
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

Etiquetas: campos, restar, resultados, tabla
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 08:59.