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

Se puede mejorar esta consulta.

Estas en el tema de Se puede mejorar esta consulta. en el foro de Mysql en Foros del Web. Con esta consulta no tengo problema me trae justo lo que quiero, pero no se hay forma de mejorar esto. @import url("http://static.forosdelweb.com/clientscript/vbulletin_css/geshi.css"); Código MySQL: Ver ...
  #1 (permalink)  
Antiguo 05/08/2011, 09:59
Avatar de arielenter  
Fecha de Ingreso: abril-2009
Mensajes: 75
Antigüedad: 15 años
Puntos: 2
Pregunta Se puede mejorar esta consulta.

Con esta consulta no tengo problema me trae justo lo que quiero, pero no se hay forma de mejorar esto.



Código MySQL:
Ver original
  1. SELECT DISTINCT (SELECT SUM(total) FROM alquiler
  2. WHERE fentrada BETWEEN '2001-01-01' AND '2011-08-04' AND estado='PAGADO' OR estado='OCUPADO') +
  3.  
  4. IFNULL((SELECT SUM(entrega) FROM alquiler
  5. WHERE fentrada BETWEEN '2011-01-08' AND '2011-05-08' AND estado='OCUPADO'),0) +
  6. IFNULL((SELECT SUM(entrega) FROM alquiler
  7. WHERE fentrada BETWEEN '2011-01-08' AND '2011-05-08' AND estado='DEBE'),0) AS xTotal;
  #2 (permalink)  
Antiguo 05/08/2011, 10:21
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Se puede mejorar esta consulta.

Hola arielenter:

Creo que deberías comenzar por decirnos qué es lo que hace tu consulta, pues son sólo ver el código puede resultar muy difícil descifrarlo. Puedes postear la estructura de tu tabla y pones algunos datos de ejemplo para ver si existe otra alternativa para lograr obtener el mismo resultad.

Por lo que puedo observar sólo consultas una tabla (alquiler) por lo que es posible que se pueda cambiar la consulta para que no tengas que hacer subconsultas. A reserva de que nos expliques la lógica de tu pregunta se me ocurre que puedes hacer algo como esto:

Código MySQL:
Ver original
  1. SUM(IF(fentrada BETWEEN '2001-01-01' AND '2011-08-04'
  2. AND estado='PAGADO' OR estado='OCUPADO', total, 0))
  3. +
  4. SUM(IF(fentrada BETWEEN '2011-01-08' AND '2011-05-08'
  5. AND estado='OCUPADO', entrega, 0))
  6. +
  7. SUM(IF(fentrada BETWEEN '2011-01-08' AND '2011-05-08'
  8.  AND estado='DEBE', entrega, 0)) xTotal
  9. alquiler

No estoy seguro siguiera si esto puede funcionar, es una consulta que lanzo vuelo, pero que no he podido probar.

Sólo tengo que hacer una observación y es con las condiciones de tu primer select, te recuerdo que por jerarquía de operadores el AND se ejecuta primero que el OR, por lo tanto cuando tienes esto:

fentrada BETWEEN '2001-01-01' AND '2011-08-04' AND estado='PAGADO' OR estado='OCUPADO'

en palabras sería "todos los registros en que fentrada esté entre el rango de fechas Y que estado sea PAGADO + que el estado sea OCUPADO, sin importar que la fentrada no esté en el rango de fechas"

Si quieres que las condiciones OR se ejecuten en el mismo orden (es decir que la condición del rango de fechas afecte a ambos estados) deberías escribir tu condición así:

Código:
fentrada BETWEEN '2001-01-01' AND '2011-08-04' 
AND (estado='PAGADO' OR estado='OCUPADO') 
o utilizando el operador IN

Código:
fentrada BETWEEN '2001-01-01' AND '2011-08-04' 
AND estado IN ('PAGADO', 'OCUPADO')
Saludos y espero tus comentarios
Leo
  #3 (permalink)  
Antiguo 05/08/2011, 10:22
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Se puede mejorar esta consulta.

Código MySQL:
Ver original
  1.     (SUM(IF(estado='PAGADO' OR estado='OCUPADO', total, 0)) +
  2.     SUM(IF(estado='OCUPADO', entrega, 0)) +
  3.     SUM(IF(estado='DEBE', entrega, 0))) xTotal
  4. FROM alquiler
  5.     fentrada BETWEEN '2001-01-01' AND '2011-08-04';
Siempre que puedas, evita hacer subconsultas en el SELECT. Es una de las formas más ineficientes que existen, porque se ejecuta al menos una vez por cada registro devuelto, y en estos casos se hace al menos tres veces.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #4 (permalink)  
Antiguo 05/08/2011, 11:06
Avatar de arielenter  
Fecha de Ingreso: abril-2009
Mensajes: 75
Antigüedad: 15 años
Puntos: 2
Respuesta: Se puede mejorar esta consulta.

Muchas gracias por responder gnzsoloyo, siempre cuando los haces, haces muy bien.

Tengo una tabla que se llama alquiler con los siguientes campos



En el campo estado yo defino 3 estado:

estado=DEBE: Cuando un cliente ya salio del hotel pero queda debiendo pudo haber entregado algo o no tambien.

estado=OCUPADO: Cuando un cliente esta todavía en el hotel y pudo haber ya entregado 1 parte por la pieza y puede que tenga también consunción.

estado=PAGADO:Cuando un cliente ya salio del hotel pudo haber entregado solo una parte por la pieza, pudo haber tenido consunción.

Con ese script lo que ago sumar de acuerdo al estado.
  #5 (permalink)  
Antiguo 05/08/2011, 12:50
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Se puede mejorar esta consulta.

Hola de nuevo arielenter:

No me quedó claro si ya resolviste la consulta o sigues con problemas.

La consulta que te propone el compañero gnzsoloyo es de hecho prácticamente la misma que te propuse yo:

Mi propuesta:
Código:
SELECT DISTINCT 
SUM(IF(fentrada BETWEEN '2001-01-01' AND '2011-08-04' 
AND estado='PAGADO' OR estado='OCUPADO', total, 0))
+
SUM(IF(fentrada BETWEEN '2011-01-08' AND '2011-05-08' 
AND estado='OCUPADO', entrega, 0))
+
SUM(IF(fentrada BETWEEN '2011-01-08' AND '2011-05-08'
AND estado='DEBE', entrega, 0)) xTotal
FROM
alquiler
La propuesta de gnzsoloyo:
Código:
SELECT 
(SUM(IF(estado='PAGADO' OR estado='OCUPADO', total, 0)) + 
SUM(IF(estado='OCUPADO', entrega, 0)) + 
SUM(IF(estado='DEBE', entrega, 0))) xTotal
FROM alquiler 
WHERE 
fentrada BETWEEN '2001-01-01' AND '2011-08-04';
En mi caso no puse la condición de la fecha en el where externo porque en tu consulta de ejemplo estabas manejando dos rangos de fechas, no uno solo:

Código:
fentrada BETWEEN '2001-01-01' AND '2011-08-04' (para el primer sum)

y 

fentrada BETWEEN '2011-01-08' AND '2011-05-08' (para los dos sum restantes)
Tal y como lo pone gnzsoloyo el rango de fechas se aplicaría igual para los tres casos, no estoy seguro si esto es correcto. De cualquier manera si resolviste consulta me alegro mucho.

Saludos
Leo.
  #6 (permalink)  
Antiguo 05/08/2011, 14:58
Avatar de arielenter  
Fecha de Ingreso: abril-2009
Mensajes: 75
Antigüedad: 15 años
Puntos: 2
Respuesta: Se puede mejorar esta consulta.

Cita:
Iniciado por leonardo_josue Ver Mensaje
Hola de nuevo arielenter:

No me quedó claro si ya resolviste la consulta o sigues con problemas.

La consulta que te propone el compañero gnzsoloyo es de hecho prácticamente la misma que te propuse yo:

Leo.
Amigo leo yo no tengo problema con mi consulta mi pregunta era si es bueno como estoy haciendo o si se podía mejorar el script
  #7 (permalink)  
Antiguo 05/08/2011, 15:56
Avatar de arielenter  
Fecha de Ingreso: abril-2009
Mensajes: 75
Antigüedad: 15 años
Puntos: 2
Respuesta: Se puede mejorar esta consulta.



leonardo_josue y gnzsoloyo Estuve probando los ejemplos que me pasaron pero no me trae la suma exacta trae menos.

Si sumamos el campo entrega solo tiene que traer 60.000 cuando estado sea DEBE ó OCUPADO.

Ahora si es estado=PAGADO solo tiene que sumar el campo TOTAL

Al ejecutar el script tiene dar como resultado: 133.000
  #8 (permalink)  
Antiguo 05/08/2011, 20:31
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Se puede mejorar esta consulta.

Mira, creo que debe haber un error de interpretación.
Dados los datos que muestras en esa tabla, y las condiciones puestas en esa primera consulta, no existe forma en que la suma te de 133.000.
Según lo que nos dices, la tabla contiene esto:
Código MySQL:
Ver original
  1. mysql> SELECT * FROM `test`.`alquiler`;
  2. +------------+------------+---------+-------------+-------+-------+---------+
  3. | idalquiler | fentrada   | entrega | consumicion | saldo | total | estado  |
  4. +------------+------------+---------+-------------+-------+-------+---------+
  5. |          1 | 2011-08-04 |       0 |           0 | 20000 | 20000 | DEBE    |
  6. |          2 | 2011-08-04 |   35000 |           0 | 15000 | 50000 | DEBE    |
  7. |          3 | 2011-08-04 |   10000 |       13000 | 20000 | 43000 | DEBE    |
  8. |          4 | 2011-08-04 |   20000 |       13000 | 10000 | 43000 | PAGADO  |
  9. |          5 | 2011-08-05 |   10000 |           0 | 20000 | 30000 | PAGADO  |
  10. |          6 | 2011-08-05 |    5000 |           0 | 15000 | 20000 | DEBE    |
  11. |          7 | 2011-08-05 |   10000 |           0 |     0 | 10000 | OCUPADO |
  12. +------------+------------+---------+-------------+-------+-------+---------+
  13. 7 rows in set (0.00 sec)
Si sumo el contenido de cada columna, daría:
Código MySQL:
Ver original
  1. mysql> SELECT SUM(entrega)entrega, SUM(consumicion)consumicion, SUM(saldo)saldo, SUM(total) total
  2.     -> FROM `test`.`alquiler`;
  3. +---------+-------------+--------+--------+
  4. | entrega | consumicion | saldo  | total  |
  5. +---------+-------------+--------+--------+
  6. |   90000 |       26000 | 100000 | 216000 |
  7. +---------+-------------+--------+--------+
  8. 1 row in set (0.00 sec)
Como podrás ver, no hay combinación de importes que de una cifra semejante a la que buscas.
Pero para ser más preciso, veremos qué pasaría si hago las sumas de tu primera consulta de separadamente, para ver qué suma:
Código MySQL:
Ver original
  1. mysql> SELECT SUM(total) suma_total
  2.     -> FROM alquiler
  3.     -> WHERE fentrada BETWEEN '2001-01-01' AND '2011-08-05' AND estado='PAGADO' OR estado='OCUPADO'
  4.     -> UNION ALL
  5.     -> SELECT SUM(entrega)
  6.     -> FROM alquiler
  7.     -> WHERE fentrada BETWEEN '2011-01-08' AND '2011-05-08' AND estado='OCUPADO'
  8.     -> UNION ALL
  9.     -> SELECT SUM(entrega)
  10.     -> FROM alquiler
  11.     -> WHERE fentrada BETWEEN '2011-01-08' AND '2011-05-08' AND estado='DEBE';
  12. +------------+
  13. | suma_total |
  14. +------------+
  15. |      83000 |
  16. |       NULL |
  17. |       NULL |
  18. +------------+
  19. 3 rows in set (0.00 sec)
Como puedes apreciar, la primera consulta da un resultado, pero las siguientes dos dan NULL, porque en realidad no hay registros que cumplan las condiciones puestas (atención, lo único que hice fue tomar las subconsultas tal y como las escribiste).

Ahora bien, si lo que deseas es verificar que entrega+consumicion+saldo es iguala total, podemos hacer así:
Código MySQL:
Ver original
  1. mysql>mysql> SELECT SUM(entrega) + SUM(consumicion) + SUM(saldo) TotalSuma, SUM(total) total
  2.     -> FROM `test`.`alquiler`
  3.     -> WHERE fentrada BETWEEN '2001-01-01' AND '2011-08-05';
  4. +-----------+--------+
  5. | TotalSuma | total  |
  6. +-----------+--------+
  7. |    216000 | 216000 |
  8. +-----------+--------+
  9. 1 row in set (0.00 sec)

Si no es eso lo que quieres suma, será mejor que nos digas exactamente qué es lo que quieres calcular, y sobre la base de qué datos, porque no se comprende bien lo que buscas.
Por otro lado, ten cuidado con las sumas que se realicen, porque ciertas operaciones aritméticas, por razonables que sean, pueden generar falsos resultados porque no se estén planteando correctamente. Hay muchos trucos y enigmas matemáticos que surgen de juegos de numeros (Cualquier duda, consultar el libro El hombre que calculaba, de Malba Tahan).
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Última edición por gnzsoloyo; 05/08/2011 a las 20:45
  #9 (permalink)  
Antiguo 05/08/2011, 21:58
Avatar de arielenter  
Fecha de Ingreso: abril-2009
Mensajes: 75
Antigüedad: 15 años
Puntos: 2
Respuesta: Se puede mejorar esta consulta.

gnzsoloyo y leonardo_josue es cierto esta perfecto script que me pasaron los 2 funcionan, yo mismo metí la pata les pase una fecha equivocada. como se darán cuenta ahí.

WHERE fentrada BETWEEN '2001-01-01' AND '2011-08-05' AND estado='PAGADO'
WHERE fentrada BETWEEN '2011-01-08' AND '2011-05-08' AND estado='OCUPADO'
WHERE fentrada BETWEEN '2011-01-08' AND '2011-05-08' AND estado='DEBE';


Cambiando la primera fecha 2001-08-05 and 2011-08-05 el resultado trae perfecto.

xTotal = 133.000

Gracias a todos por ayudar. me merezco un toki jejeje
__________________
www.enterpy.net

Etiquetas: mejorar, select
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 05:36.