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

Rango de fechas seleccionar inverso

Estas en el tema de Rango de fechas seleccionar inverso en el foro de Mysql en Foros del Web. Estoy realizando una reservas de bicicletas he intentado realizarlo a siguiendo el hilo de [URL="http://www.forosdelweb.com/f86/seleccionar-datos-fuera-rango-especifico-938177/"]http://www.forosdelweb.com/f86/seleccionar-datos-fuera-rango-especifico-938177/[/URL] pero no lo he conseguido por eso pido ayuda. Gracias, ...
  #1 (permalink)  
Antiguo 31/08/2011, 15:05
 
Fecha de Ingreso: agosto-2009
Mensajes: 8
Antigüedad: 14 años, 7 meses
Puntos: 0
Rango de fechas seleccionar inverso

Estoy realizando una reservas de bicicletas he intentado realizarlo a siguiendo el hilo de [URL="http://www.forosdelweb.com/f86/seleccionar-datos-fuera-rango-especifico-938177/"]http://www.forosdelweb.com/f86/seleccionar-datos-fuera-rango-especifico-938177/[/URL] pero no lo he conseguido por eso pido ayuda. Gracias, muchas gracias.

Tengo una base de datos que se llama reservas y es así

id | bici | fecha_inicio | fecha_final
1 | bici1 | 2011-08-31 | 2011-09-02
2 | bici1 | 2011-09-01 | 2011-09-02
3 | bici1 | 2011-08-01 | 2011-08-02
4 | bici2 | 2011-09-01 | 2011-09-02


Quiero seleccionar por ejemplo las bici1 que no esten reservadas entre 2011-09-01 y 2011-09-02. Tendría que ser la id=3

He intentado muchas cosas, la última es
SELECT * FROM reservas WHERE bici="bici1" NOT IN ( SELECT id FROM reservas WHERE fecha_inicial<="2011-09-01" AND fecha_final>="2011-09-02" ) AND bici="bici1"

Agradecería mucho que me diesen una mano

Gracias de antemano
  #2 (permalink)  
Antiguo 31/08/2011, 15:11
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, 4 meses
Puntos: 2658
Respuesta: Rango de fechas seleccionar inverso

Código MySQL:
Ver original
  1. FROM reservas
  2. WHERE bici='bici1'
  3. AND fecha_inicial NOT BETWEEN '2011-09-01' AND '2011-09-02;
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 01/09/2011, 06:17
 
Fecha de Ingreso: agosto-2009
Mensajes: 8
Antigüedad: 14 años, 7 meses
Puntos: 0
Respuesta: Rango de fechas seleccionar inverso

No me funciona esta solución gnzsoloyo ya que también se selecciona la id=1 (ademas de la id=3 que es la única solución), esto pasa porque la reserva id=1 tiene una fecha_inicio distinta a los rangos BETWEEN '2011-09-01' AND '2011-09-02';

La verdad es que no sé si solo con Mysql se podrá solucionar este inconveniente.
  #4 (permalink)  
Antiguo 02/09/2011, 09:20
Avatar de Rod_Man_mx  
Fecha de Ingreso: agosto-2009
Mensajes: 69
Antigüedad: 14 años, 8 meses
Puntos: 4
Respuesta: Rango de fechas seleccionar inverso

Para que la solución del post que mencionas te funcione debes de tener una tabla de con todas las bicicletas que tengas, y hacer la comparación, es decir, primero sacas que bicicletas tienes ocupadas en esas fechas, y despues haces el match (usando NOT IN) con las bicicletas que tienes en existencia.
  #5 (permalink)  
Antiguo 02/09/2011, 09:35
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, 4 meses
Puntos: 2658
Respuesta: Rango de fechas seleccionar inverso

Cita:
Iniciado por josecastro Ver Mensaje
No me funciona esta solución gnzsoloyo ya que también se selecciona la id=1 (ademas de la id=3 que es la única solución), esto pasa porque la reserva id=1 tiene una fecha_inicio distinta a los rangos BETWEEN '2011-09-01' AND '2011-09-02';

La verdad es que no sé si solo con Mysql se podrá solucionar este inconveniente.
Poderse, se puede, pero tienes que definirnos mejor cuál es el rango que buscas y de qué campo lo tenemos que sacar.

Si quieres lo de todo el período, pero sólo las fechas de entrada/salida contenidas, como ambas están en campos distintos, debes forzosamente poner un doble BETWEEN

Por ejemplo:
Código MySQL:
Ver original
  1. FROM reservas
  2.     bici='bici1'
  3.     AND
  4.     fecha_inicial NOT BETWEEN '2011-09-01' AND '2011-09-02'
  5.     AND
  6.     fecha_final NOT BETWEEN '2011-09-01' AND '2011-09-02';

Nota: Ten en cuenta que para toda comparación donde uses un rango tal que el valor comparado sea "igual o mayor" a uno dado e "igual o menor" otro, debes usar BETWEEN, porque el algoritmo interno de MySQL no es igual que cuando se usan ">=" y "<=".
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #6 (permalink)  
Antiguo 02/09/2011, 11:07
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años
Puntos: 300
Respuesta: Rango de fechas seleccionar inverso

Creo que esto también funciona

SELECT * FROM reservas WHERE bici= 'bici1' AND id NOT IN (SELECT id FROM `reservas` WHERE fecha_fin >= '2011-09-02' AND fecha_inicio <= '2011-09-01')
  #7 (permalink)  
Antiguo 02/09/2011, 12:32
 
Fecha de Ingreso: agosto-2009
Mensajes: 8
Antigüedad: 14 años, 7 meses
Puntos: 0
Respuesta: Rango de fechas seleccionar inverso

Gracias por los aportes, me explicaré mejor.
El problema radica cuando se seleccionan fechas intermedias.
Lo he logrado solucionar con un monstruo de php pero ahora me ha picado el orgullo e intento conseguir la solución en SQL, si no se encuentra otra solución publicaré el de php

Tengo está gráfica que muestra mejor:


id=Numero de la bici
bici=Es el modelo de la bici (puede tener varias bicis del mismo modelo)
fechainicio=Fecha inicio reserva
fechafinal=Fecha final de la reserva

NO TENGO los valores intermedios

El SQL es:
Código SQL:
Ver original
  1. CREATE TABLE `reservas` (
  2.   `id` INT(11) NOT NULL AUTO_INCREMENT,
  3.   `bici` text,
  4.   `fechainicio` DATE DEFAULT NULL,
  5.   `fechafinal` DATE DEFAULT NULL,
  6.   PRIMARY KEY (`id`)
  7. ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
  8.  
  9. --
  10. -- Volcar la base de datos para la tabla `reservas`
  11. --
  12.  
  13. INSERT INTO `reservas` VALUES(4, 'BT250', '2011-09-01', '2011-09-03');
  14. INSERT INTO `reservas` VALUES(3, 'BT250', '2011-09-03', '2011-09-03');
  15. INSERT INTO `reservas` VALUES(2, 'BT250', '2011-08-30', '2011-08-31');
  16. INSERT INTO `reservas` VALUES(1, 'BT250', '2011-08-30', '2011-09-01');
  17. INSERT INTO `reservas` VALUES(5, 'BT300', NULL, NULL);

Mi pregunta es como buscar una bici modelo BT250 que no esté reservada el 2011-08-31 (La unica solucion son la id=3 y el id=4)

La he probado con esta solucion que me dio jurena y me devuelve las bicis BT250 1,3 y la 4
Código SQL:
Ver original
  1. SELECT * FROM reservas WHERE bici= 'BT250' AND id NOT IN (SELECT id FROM reservas  WHERE fechainicio >= '2011-08-31' AND fechafinal <= '2011-08-31')

Y con esta otra solución de gnzsoloyo me devuelve la 1, 3 y la 4
Código SQL:
Ver original
  1. SELECT * FROM reservas
  2. WHERE
  3. bici='BT250'
  4. AND
  5. fechainicio NOT BETWEEN '2011-08-31' AND '2011-08-31'
  6. AND
  7. fechafinal NOT BETWEEN '2011-08-31' AND '2011-08-31';

Gracias
  #8 (permalink)  
Antiguo 02/09/2011, 12:56
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, 4 meses
Puntos: 2658
Respuesta: Rango de fechas seleccionar inverso

probemos con:
Código MySQL:
Ver original
  1. SELECT * FROM reservas
  2.     bici='BT250'
  3.     AND
  4.     '2011-08-31' NOT BETWEEN fechainicial AND fechafinal;
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #9 (permalink)  
Antiguo 02/09/2011, 13:19
 
Fecha de Ingreso: agosto-2009
Mensajes: 8
Antigüedad: 14 años, 7 meses
Puntos: 0
Respuesta: Rango de fechas seleccionar inverso

Oye! este si funciona gnzsoloyo, eres un crack!

Entonces sería cosa de crear la consulta en php con los rango intermedios cuando el cliente busque entre 2 rangos.

Por ejemplo entre: 2011-08-30 y 2011-09-01 una bici BT250

Código SQL:
Ver original
  1. SELECT * FROM reservas WHERE bici='BT250'
  2. AND ('2011-08-30' NOT BETWEEN fechainicio AND fechafinal)
  3. AND ('2011-08-31' NOT BETWEEN fechainicio AND fechafinal)
  4. AND ('2011-09-01' NOT BETWEEN fechainicio AND fechafinal);


¡Muchas gracias, de veras!
  #10 (permalink)  
Antiguo 02/09/2011, 16:02
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, 4 meses
Puntos: 2658
Respuesta: Rango de fechas seleccionar inverso

Si estás buscando más de un rango, lo que corresponde es usar OR y no AND porque tienes que considerar que si eliges dos rangos completamente distintos, no pueden darse los dos al mismo al mismo tiempo. E incluso deberás considerar si los rangos están contenido uno en otro, cruzados, etc.
En ese tipo de selecciones múltiples tienes que tener cuidado con los criterios de búsqueda, deben ser consistentes o los resultados serán erráticos.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #11 (permalink)  
Antiguo 02/09/2011, 16:42
 
Fecha de Ingreso: agosto-2009
Mensajes: 8
Antigüedad: 14 años, 7 meses
Puntos: 0
Respuesta: Rango de fechas seleccionar inverso

Muchas gracias a todos, dejo el código completo gracias a lo escrito por gnzsoloyo, por si a alguien le sirviera en algún momento.

Código PHP:
Ver original
  1. <?php
  2.  
  3. $fecha1 = '2011-09-01'; // Fecha inicial de reserva del cliente
  4. $fecha2 = '2011-09-03'; // Fecha final de reserva del cliente
  5. $bici = 'BT250'; // Modelo de bici
  6.  
  7. // Función para sumar días
  8. function sumaDia($fechainicial,$dia){  
  9.     list($year,$mon,$day) = explode('-',$fechainicial);
  10.     return date('Y-m-d',mktime(0,0,0,$mon,$day+$dia,$year));       
  11. }
  12.  
  13. // Creamos el rango de fechas entre $Fecha1 y $Fecha2
  14. // Creamos la cadena de consulta $asignacion2
  15. for ($i = 0;;$i++) {
  16.     if ($fecha2 < sumaDia($fecha1,$i)) { break; }
  17.     $asignacion = " AND ('". sumaDia($fecha1,$i) ."' NOT BETWEEN fechainicio AND fechafinal)";
  18.     $asignacion2 .= $asignacion;
  19. }
  20.  
  21. // Hacemos la consulta
  22. $muestra="SELECT * FROM reservas WHERE bici='$bici' $asignacion2";
  23. $resultado=mysql_query($muestra);
  24. while ($fila=mysql_fetch_array($resultado)) {
  25.     echo $id = $fila['id'];
  26.     }
  27. ?>

Etiquetas: fechas, rango
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:20.