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

Consulta selectiva

Estas en el tema de Consulta selectiva en el foro de Mysql en Foros del Web. Hola a todos, quisiera ver si alguien me puede ayudar en la siguiente consulta: tengo una tabla en MySQL con varios campos, entre ellos ref, ...
  #1 (permalink)  
Antiguo 23/04/2012, 22:32
 
Fecha de Ingreso: febrero-2011
Mensajes: 85
Antigüedad: 13 años, 2 meses
Puntos: 3
Consulta selectiva

Hola a todos, quisiera ver si alguien me puede ayudar en la siguiente consulta: tengo una tabla en MySQL con varios campos, entre ellos ref, mov, imp.

La consulta es la siguiente si existen dos registros donde ref e imp son iguales, y mov sea 1 y el otro 2, que no me los muestre

Reg ref mov imp
--------------------------------
1 "A1" "1" 500.00
2 "A2" "1" 200.00
3 "A3" "1" 300.00
4 "A4" "1" 500.00
5 "A5" "1" 4500.00
6 "A1" "2" 500.00
7 "A6" "1" 500.00
8 "A5" "2" 4500.00

En la tabla anterior solo tendria que mostrarme los registros 2,3,4,7 ya que el 1 corresponde con el 6 y el 5 corresponde con el 8.

No se si me explique,

Gracias Anticipadas. y saludos
  #2 (permalink)  
Antiguo 24/04/2012, 01:04
Avatar de REVIDEUX  
Fecha de Ingreso: septiembre-2011
Ubicación: Lima, Peru, Peru
Mensajes: 23
Antigüedad: 12 años, 7 meses
Puntos: 0
Respuesta: Consulta selectiva

Hola que tal Computer_si, espero que esto te sirva:

select f.reg,f.ref, f.mov,f.imp from TablaProof as f
left join
(select t.reg reg1, c.reg reg2 from TablaProof as t left join
(select * from TablaProof) as c
on (t.ref = c.ref ) where (t.mov ='1' and c.mov = '2')
and (t.imp = c.imp)) as t
on f.reg = t.reg1 or f.reg = t.reg2
where t.reg1 is null and t.reg2 is null

Esto esta en SQL Server pero creo que de aqui ya puedes adaptarlo sin inconvenientes.

Suerte, hasta otra oportunidad.
  #3 (permalink)  
Antiguo 24/04/2012, 08:13
 
Fecha de Ingreso: febrero-2011
Mensajes: 85
Antigüedad: 13 años, 2 meses
Puntos: 3
Respuesta: Consulta selectiva

Hola REVIDEUX adapte el codigo de la siguiente manera:

include 'conexion.php';
$link = conectar();

$sql="SELECT f.regId, f.ref, f.tipMov, f.imp FROM cuentas AS f LEFT JOIN (SELECT t.regId reg1, t.regId reg2, t.ref, t.tipMov, t.imp FROM cuentas AS t LEFT JOIN (SELECT * FROM cuentas) AS c ON (t.ref = c.ref ) WHERE (t.tipMov ='1' and c.tipMov = '2') AND (t.imp = c.imp)) AS t ON f.regId = t.reg1 OR f.regId = t.reg2 WHERE t.reg1 IS null and t.reg2 IS null ORDER BY f.regId ASC";

$result = mysql_query($sql, $link) or die(mysql_error());
$row = mysql_fetch_row($result);
if($row < 0){
echo "! ! No selecciono nada! !";
}else{
while($row=mysql_fetch_array($result)) {
echo $row[0].'--'.$row[1].'--'.$row[2].'--'.$row[3].'<br>';
}
}
desconectar();

los campos en la tabla

regId int(10)
ref varchar(10)
tipMov int(2)
imp int(15)

y la consulta me muestra

3--A3--1--300
4--A4--1--500
6--A1--2--500
7--A6--1--500
8--A5--2--4500

Donde puede estar la falla, saludos y gracias por responder
  #4 (permalink)  
Antiguo 24/04/2012, 08:39
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Consulta selectiva

Hola computer_si:

Creo que la consulta podría simplificarse un poco, checa este script:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM tabla;
  2. +------+------+------+---------+
  3. | reg  | ref  | mov  | imp     |
  4. +------+------+------+---------+
  5. |    1 | A1   | 1    |  500.00 |
  6. |    2 | A2   | 1    |  200.00 |
  7. |    3 | A3   | 1    |  300.00 |
  8. |    4 | A4   | 1    |  500.00 |
  9. |    5 | A5   | 1    | 4500.00 |
  10. |    6 | A1   | 2    |  500.00 |
  11. |    7 | A6   | 1    |  500.00 |
  12. |    8 | A5   | 2    | 4500.00 |
  13. +------+------+------+---------+
  14. 8 rows in set (0.00 sec)
  15.  
  16.  
  17. mysql> SELECT * FROM tabla T1 WHERE
  18.     -> (T1.mov = '1' AND NOT EXISTS (
  19.     -> SELECT reg FROM tabla T2
  20.     -> WHERE T1.ref = T2.ref AND T1.imp = T2.imp AND T2.mov = '2'));
  21. +------+------+------+--------+
  22. | reg  | ref  | mov  | imp    |
  23. +------+------+------+--------+
  24. |    2 | A2   | 1    | 200.00 |
  25. |    3 | A3   | 1    | 300.00 |
  26. |    4 | A4   | 1    | 500.00 |
  27. |    7 | A6   | 1    | 500.00 |
  28. +------+------+------+--------+
  29. 4 rows in set (0.00 sec)
  30.  
  31. mysql> SELECT * FROM tabla T1 WHERE
  32.     -> (T1.mov = '1' AND NOT EXISTS (
  33.     -> SELECT reg FROM tabla T2
  34.     -> WHERE T1.ref = T2.ref AND T1.imp = T2.imp AND T2.mov = '2')) OR
  35.     -> (T1.mov = '2' AND NOT EXISTS (
  36.     -> SELECT reg FROM tabla T2
  37.     -> WHERE T1.ref = T2.ref AND T1.imp = T2.imp AND T2.mov = '1'));
  38. +------+------+------+--------+
  39. | reg  | ref  | mov  | imp    |
  40. +------+------+------+--------+
  41. |    2 | A2   | 1    | 200.00 |
  42. |    3 | A3   | 1    | 300.00 |
  43. |    4 | A4   | 1    | 500.00 |
  44. |    7 | A6   | 1    | 500.00 |
  45. +------+------+------+--------+
  46. 4 rows in set (0.00 sec)

La segunda consulta sería para considerar que existan registros con mov = 2 pero sin mov = 1 aunque según tu lógica de negocio no sé si esto pueda ocurrir.

Saludos
Leo
  #5 (permalink)  
Antiguo 24/04/2012, 09:50
 
Fecha de Ingreso: febrero-2011
Mensajes: 85
Antigüedad: 13 años, 2 meses
Puntos: 3
Respuesta: Consulta selectiva

Gracias Leonardo_josue, modifique el codigo y ya funciona:

include 'conexion.php';
$link = conectar();

//$sql="SELECT f.regId, f.ref, f.tipMov, f.imp FROM cuentas AS f LEFT JOIN (SELECT t.regId reg1, t.regId reg2, t.ref, t.tipMov, t.imp FROM cuentas AS t LEFT JOIN (SELECT * FROM cuentas) AS c ON (t.ref = c.ref ) WHERE (t.tipMov ='1' and c.tipMov = '2') AND (t.imp = c.imp)) AS t ON f.regId = t.reg1 OR f.regId = t.reg2 WHERE t.reg1 IS null and t.reg2 IS null ORDER BY f.regId ASC";

$sql="SELECT * FROM cuentas T1 WHERE(T1.tipMov = '1' AND NOT EXISTS (SELECT ref, imp, tipMov FROM cuentas T2 WHERE T1.ref = T2.ref AND T1.imp = T2.imp AND T2.tipMov = '2'))";

$result = mysql_query($sql, $link) or die(mysql_error());
$row = mysql_fetch_row($result);
if($row < 0){
echo "! ! No selecciono nada! !";
}else{
echo $row[0].'--'.$row[1].'--'.$row[2].'--'.$row[3].'<br>';
while($row=mysql_fetch_array($result)) {
echo $row[0].'--'.$row[1].'--'.$row[2].'--'.$row[3].'<br>';
}
}
desconectar();

Referente a lo que comentas del tipo de negocio, tomare en cuenta la segunda consulta, pero siempre va a existir primero el tipo de movimiento "1", ahora la siguiente problematica es cuando el tipo de movimiento es dos pero el importe no corresponde esto es tomando en cuenta la tabla anterior de la siguiente manera:

+------+------+------+---------+
| reg | ref |tipMov | imp |
+------+------+------+---------+
| 1 | A1 | 1 | 500.00 |
| 2 | A2 | 1 | 200.00 |
| 3 | A3 | 1 | 300.00 |
| 4 | A4 | 1 | 500.00 |
| 5 | A5 | 1 | 4500.00 |
| 6 | A1 | 2 | 500.00 |
| 7 | A6 | 1 | 500.00 |
| 8 | A5 | 2 | 500.00 |
| 9 | A5 | 2 | 2500.00 |
| 10 | A5 | 2 | 500.00 |
+------+------+------+---------+

En este caso deberia de mostrarme igual los registros 2,3,4,7 y el 5 pero con un importe de 1000, ya que la suma de los registros 8,9,10 es igual a 3500.

Otra pregunta, sabes porque cuando entro al while, y envio el echo de los registros siempre me envia desde el segundo.

Se podra hacer esto, saludos y gracias anticipadas.
  #6 (permalink)  
Antiguo 24/04/2012, 11:10
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Consulta selectiva

Hola de nuevo computer_si:

Lo que planteas ahora es completamente distinto al problema original, ya que aquí será necesario hacer una agrupación de registros, ya que cada ref puede tener uno o varios registros con mov=2... (y supongo que será posible que también tenga varios registros con mov=1)

Si estoy en lo cierto, esto parece ser una especie de cargos y abonos, o ventas y compras, donde el resultado que esperas sea aquellas cuentas que no están saldadas... Para esto, hay muchas formas de poder abordar el problema, por ejemplo checa este script:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM tabla;
  2. +------+------+------+---------+
  3. | reg  | ref  | mov  | imp     |
  4. +------+------+------+---------+
  5. |    1 | A1   | 1    |  500.00 |
  6. |    2 | A2   | 1    |  200.00 |
  7. |    3 | A3   | 1    |  300.00 |
  8. |    4 | A4   | 1    |  500.00 |
  9. |    5 | A5   | 1    | 4500.00 |
  10. |    6 | A1   | 2    |  500.00 |
  11. |    7 | A6   | 1    |  500.00 |
  12. |    8 | A5   | 2    |  500.00 |
  13. |    9 | A5   | 2    | 2500.00 |
  14. |   10 | A5   | 2    |  500.00 |
  15. +------+------+------+---------+
  16. 10 rows in set (0.07 sec)
  17.  
  18. mysql> SELECT ref,
  19.     -> IFNULL((SELECT SUM(T2.imp) FROM tabla T2
  20.     -> WHERE T1.ref = T2.ref AND T2.mov = 1), 0) -
  21.     -> IFNULL((SELECT SUM(T2.imp) FROM tabla T2
  22.     -> WHERE T1.ref = T2.ref AND T2.mov = 2), 0) saldo
  23.     -> FROM tabla T1 GROUP BY ref HAVING saldo != 0;
  24. +------+---------+
  25. | ref  | saldo   |
  26. +------+---------+
  27. | A2   |  200.00 |
  28. | A3   |  300.00 |
  29. | A4   |  500.00 |
  30. | A5   | 1000.00 |
  31. | A6   |  500.00 |
  32. +------+---------+
  33. 5 rows in set (0.00 sec)


En el select se realizan dos subconsultas (una para obtener la sumatoria de los mov=1 para cada ref y otra para obtener la sumatoria de los mov=2), se realiza la resta y se muestran sólo aquellos registros que tengan un saldo distinto de 0. Esta es posible que no sea la manera más eficiente de hacer lo que quieres, pero es una de ellas.

En cuanto a la pregunta del WHILE, esta no corresponde a un tema de MySQL, por lo que debes publicarla en el foro correspondiente,

http://www.forosdelweb.com/f18/

Saludos
Leo.
  #7 (permalink)  
Antiguo 24/04/2012, 11:59
 
Fecha de Ingreso: febrero-2011
Mensajes: 85
Antigüedad: 13 años, 2 meses
Puntos: 3
Respuesta: Consulta selectiva

Gracias nuevamente Leonardo_josue:

Todavia no pruebo el codigo, pero al igual que el anterior, debe de funcionar, en cuanto al comentario de que no es la manera mas eficiente, porque el comentario??

Desde tu punto de vista cual seria la manera mas eficiente de hacerlo, tambien te comento que estas en lo cierto en cuanto al planteamiento, lo pienso implementar en manejar cargos y abonos.

Saludos y gracias nuevamente, tambien tomo en cuenta lo del While para publicar o buscar en el foro correspndiente.
  #8 (permalink)  
Antiguo 24/04/2012, 12:08
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Consulta selectiva

Hola de nuevo:

El uso de subconsultas puede ocasionar que una consulta no sea eficiente, sobre todo cuando manejas un número importante de registros... Si fuera el caso, es posible que se tenga que utilizar alguna otra alternativa como el uso de join's, procedimientos almacenados, tablas temporales, vistas etc... Es por eso que menciono que la consulta puede no ser del todo eficiente. Si manejas un número reducido de registros entonces no deberías tener problemas, pero siempre hay que evaluar el performance de las consultas.

Saludos
Leo.
  #9 (permalink)  
Antiguo 24/04/2012, 12:28
 
Fecha de Ingreso: febrero-2011
Mensajes: 85
Antigüedad: 13 años, 2 meses
Puntos: 3
Respuesta: Consulta selectiva

Que tal Leonardo

Referente a los joins, me imagino que quieres decir que lo maneje en tablas separadas y hacer uniones, en cuanto a las consultas almacenadas, me habian comentado que no son muy eficientes, y referente a tablas temporales, soy muy adepto a ellas, nadamas que pense que haciendo los querys directos podria ahorrarme tiempo.

Que opinion me das al respecto de lo que comento de las consultas almacenadas.

Saludos y nuevamente gracias anticipadas.
  #10 (permalink)  
Antiguo 24/04/2012, 12:40
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Consulta selectiva

Desde mi punto de vista muy particular, los procedimientos almacenados son una muy buena opción para consultas complejas... para consultas sencillas pueden resultar un esfuerzo innecesario.

Decir que una opción (consultas simples vs procedimientos almacenados) es mejor que la otra no es tan fácil de decir, depende del escenario que tengas. En lo particular siempre he optado por un híbrido es decir, utilizar procedimientos almacenados para consultas complejas o para operaciones de Insert, Delete, Update sobre tablas, ya que puedes tener un mejor control sobre quién hace que cosa... para cuestiones sencillas entonces opto por ejecutar directamente la consulta.

Independientemente de lo que elijas, revisa siempre no se afecte el rendimiento del servidor.

Saludos
Leo.
  #11 (permalink)  
Antiguo 24/04/2012, 13:44
 
Fecha de Ingreso: febrero-2011
Mensajes: 85
Antigüedad: 13 años, 2 meses
Puntos: 3
Respuesta: Consulta selectiva

Ok Leonardo

Tomare encuenta tus puntos de vista, ya que de todo se aprende. En cuanto a que es mas rapido y eficiente, se puede hacer un query directo y con consulta almacenda y barrer la base de datos, y esto seria un indicativo para ver el mejor desempeño. es pregunta??

Saludos
  #12 (permalink)  
Antiguo 24/04/2012, 16:39
 
Fecha de Ingreso: febrero-2011
Mensajes: 85
Antigüedad: 13 años, 2 meses
Puntos: 3
Respuesta: Consulta selectiva

Hola Leonardo

Ya cheque el query como me lo posteaste, y en efecto la ref y el saldo si me los da correctos, en donde tengo problemas es al agregar la columna de tipo en teoria me debera de salir "1", por que es el saldo de una ref A5 de tipo 1, pero me arroja el siguiente resultado:

A2|200|1
A3|300|1
A4|500|1
A5|1000|2
A6|500|1

Me imagino que el barrido es el siguiente, primero suma todo lo que encuentra con 1, en ese punto tipMov todavia es 1, despues suma lo que encuentra con 2 y en este punto tipMov ya vale 2, es por eso que tipMov siempre me sale como 2 aunque la suma de tipMov1 sea mayor que tipMov 2.

Es correcto??

Modifique de esta forma la consulta y no me funciona

"SELECT ref, IF( saldo > 0,1,2) tMov, (IFNULL((SELECT SUM(T2.imp) FROM cuentas T2 WHERE T1.ref = T2.ref AND T2.tipMov = 1), 0) - IFNULL((SELECT SUM(T2.imp) FROM cuentas T2 WHERE T1.ref = T2.ref AND T2.tipMov = 2), 0)) saldo FROM cuentas T1 GROUP BY ref HAVING saldo != 0";

Pero de esta forma la consulta si me funciona, (sera muy ineficiente de esta forma??)

"SELECT ref, IF((IFNULL((SELECT SUM(T2.imp) FROM cuentas T2 WHERE T1.ref = T2.ref AND T2.tipMov = 1), 0) - IFNULL((SELECT SUM(T2.imp) FROM cuentas T2 WHERE T1.ref = T2.ref AND T2.tipMov = 2), 0)) > 0,1,2) tMov, (IFNULL((SELECT SUM(T2.imp) FROM cuentas T2 WHERE T1.ref = T2.ref AND T2.tipMov = 1), 0) - IFNULL((SELECT SUM(T2.imp) FROM cuentas T2 WHERE T1.ref = T2.ref AND T2.tipMov = 2), 0)) saldo FROM cuentas T1 GROUP BY ref HAVING saldo != 0";

A2|1|200
A3|1|300
A4|1|500
A5|1|1000
A6|1|500

Saludos nuevamente

Última edición por computer_si; 24/04/2012 a las 17:10

Etiquetas: registros, selectiva, sql, tabla, campos
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 20:40.