[MySQL] Comparazione data per sistema di prenotazioni

xone

Utente Attivo
4 Apr 2014
180
14
18
Salento
Salve a tutti, sto ultimando uno script per prenotazioni ma sto avendo un problema nel comparare le date per sapere se una camera è disponibile o meno in determinate date.

Ho provato in questo modo ma non funge:

$sq1 = "SELECT * FROM booking WHERE arrivo <= '$arrivo' AND partenza >= '$arrivo' OR arrivo <= '$arrivo' ";

A me serve che il controllo avvenga in modo da non intersecare le date ad esempio se io ho nel db le date:

Arrivo: 2017-05-15 - Partenza: 2017-05-20

- se ad un controllo si imposta: arrivo 13 e partenza 15 deve risultare occupata;
- se ad un controllo si imposta: arrivo 15 e partenza 19 deve risultare occupata;
- se ad un controllo si imposta: arrivo 14 e partenza 22 deve risultare occupata;
- se ad un controllo si imposta: arrivo 16 e partenza 20 deve risultare occupata;
- se ad un controllo si imposta: arrivo 17 e partenza 25 deve risultare occupata;

Grazie in anticipo a chi può essere d'aiuto.
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.042
146
63
PR
www.borgo-italia.it
ciao
immagino che un tuo cliente inputi una data di arrivo ($arrivo) e una di partenza ($partenza)
PHP:
$query="SELECT * FROM booking WHERE (arrivo BETWEEN '$arrivo' AND $partenza) OR (partenza BETWEEN '$arrivo' AND $partenza)";
in questo modo dovresti ottenere le camere OCCUPATE (una delle date richieste interseca)

PHP:
$query= "SELECT * FROM booking WHERE (arrivo NOT BETWEEN '$arrivo' AND $partenza) AND (partenza NOT BETWEEN '$arrivo' AND $partenza)";
in questo modo dovresti ottenere le camere LIBERE (le date richieste non intersecano)
prova, anche se non so dirti se funziona
 

livellacri

Utente Attivo
18 Ago 2016
108
13
18
io farei in questo modo, testato e funzionante:
PHP:
$sql1 = "SELECT * FROM booking WHERE partenza<'$arrivo' OR (partenza>'$arrivo' AND arrivo>'$partenza')";
con questa query vengono selezionate le camere libere
 

xone

Utente Attivo
4 Apr 2014
180
14
18
Salento
leggi questa discussione, OLD_FAN propone una soluzione molto facile da applicare
https://forum.mrwebmaster.it/thread...-di-tempo-si-sovrappongono.43065/#post-186970
ps
ho fatto test con i possibili incroci tutti superati positivamente
trovi il fiddle con i test
Purtroppo questo sistema non funge al 100%, perchè se metto le date centrali dice che è occupata, ma se metto dal 16/05 al 22/05 mi dice che è libera ma non può essere visto che io gia nel db ho occupato dal 15/05 al 20/05
 

xone

Utente Attivo
4 Apr 2014
180
14
18
Salento
io farei in questo modo, testato e funzionante:
PHP:
$sql1 = "SELECT * FROM booking WHERE partenza<'$arrivo' OR (partenza>'$arrivo' AND arrivo>'$partenza')";
con questa query vengono selezionate le camere libere
Non va bene, mi porta camera libera se seleziono dal 16/05 al 21/05 invece nel db ho gia 15/05 al 20/05
 

xone

Utente Attivo
4 Apr 2014
180
14
18
Salento
ciao
immagino che un tuo cliente inputi una data di arrivo ($arrivo) e una di partenza ($partenza)
PHP:
$query="SELECT * FROM booking WHERE (arrivo BETWEEN '$arrivo' AND $partenza) OR (partenza BETWEEN '$arrivo' AND $partenza)";
in questo modo dovresti ottenere le camere OCCUPATE (una delle date richieste interseca)

PHP:
$query= "SELECT * FROM booking WHERE (arrivo NOT BETWEEN '$arrivo' AND $partenza) AND (partenza NOT BETWEEN '$arrivo' AND $partenza)";
in questo modo dovresti ottenere le camere LIBERE (le date richieste non intersecano)
prova, anche se non so dirti se funziona
Non vanno bene nesuno dei due casi, al primo mi dice che è libera ma in realtà è occupata, al secondo mi dice che è occupata anche se seleziono date libere.. :|
 

xone

Utente Attivo
4 Apr 2014
180
14
18
Salento
Grazie Marino51 questo metodo sembra essere l'unico funzionante. Grazie anche a Borgo Italia e Livellacri per l'aiuto datomi. Il problema sembra essere risolto.
 

marino51

Utente Attivo
28 Feb 2013
2.912
162
63
Lombardia
Il problema sembra essere risolto.
ho comunque riprovato il metodo suggerito e mi sembra sia ottimo,
arrivo 15 e partenza 20 deve risultare occupata (ev2 sovrapposto coincidente)
ev1 : 20170515 - 20170520 ev2 : 20170515 - 20170520
occupato

arrivo 14 e partenza 21 deve risultare occupata (ev2 sovrapposto esterno)
ev1 : 20170515 - 20170520 ev2 : 20170514 - 20170521
occupato

arrivo 16 e partenza 19 deve risultare occupata (ev2 sovrapposto interno)
ev1 : 20170515 - 20170520 ev2 : 20170516 - 20170519
occupato

arrivo 15 e partenza 19 deve risultare occupata (ev2 inizio sovrapposto ev1 inizio)
ev1 : 20170515 - 20170520 ev2 : 20170515 - 20170519
occupato

arrivo 20 e partenza 22 deve risultare occupata (ev2 inizio sovrapposto ev1 fine)
ev1 : 20170515 - 20170520 ev2 : 20170520 - 20170522
occupato

arrivo 13 e partenza 15 deve risultare occupata (ev2 fine sovrapposto ev1 inizio)
ev1 : 20170515 - 20170520 ev2 : 20170513 - 20170515
occupato

arrivo 16 e partenza 20 deve risultare occupata (ev2 fine sovrapposto ev1 fine)
ev1 : 20170515 - 20170520 ev2 : 20170516 - 20170520
occupato

arrivo 17 e partenza 17 deve risultare occupata (ev2 1 giorno interno)
ev1 : 20170515 - 20170520 ev2 : 20170517 - 20170517
occupato

arrivo 13 e partenza 14 deve risultare libera (ev2 precede)
ev1 : 20170515 - 20170520 ev2 : 20170513 - 20170514
libero

arrivo 21 e partenza 22 deve risultare libera (ev2 segue)
ev1 : 20170515 - 20170520 ev2 : 20170521 - 20170522
libero
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.042
146
63
PR
www.borgo-italia.it
ciao
per dovere di cronaca, anche se non so come è fatta la tabella, ho provato con una tabella fatta così
Codice:
id int(6) NOT NULL AUTO_INCREMENT,
camera varchar(3) NOT NULL,
arrivo varchar(10) NOT NULL,
partenza varchar(10) NOT NULL,
PRIMARY KEY (id)
lo script
PHP:
<?php
//...
$arrivo="2017-07-30";//$_POST['arrivo'];//formato YYYY-mm-gg
$partenza="2017-08-04";//$_POST['pa_mese'];
$query_occ="SELECT * FROM book WHERE arrivo BETWEEN '$arrivo' AND '$partenza' OR partenza BETWEEN '$arrivo' AND '$partenza'";
$ris=mysqli_query($conn,$query_occ);
$occ=array();//aggiunto per camere libere
if(mysqli_num_rows($ris)>0){
    while($cam=mysqli_fetch_assoc($ris)){
        $occ[$cam['camera']]="occupata";//controllo per camere libere
        echo "la camera ".$cam['camera']." è occupata<br>";
    }
}
echo "<br>";
    $query_lib= "SELECT * FROM book WHERE (arrivo NOT BETWEEN '$arrivo' AND '$partenza' AND partenza NOT BETWEEN '$arrivo' AND '$partenza')";
    $ris=mysqli_query($conn,$query_lib);
    if(mysqli_num_rows($ris)>0){
        while($cam=mysqli_fetch_assoc($ris)){
            if($occ[$cam['camera']]!="occupata"){
                echo "la camera ".$cam['camera']." è libera<br>";
            }
        }
        echo "<br>";
    }
//....
?>
estrae le camere occupate nell'intervallo richiesto, nel post precedente avevo fatto una dimenticanza nel mettere gli apici
diverso è per le camere libere perche se es ho in tabella
Codice:
3 'c1' '2017-08-01' '2017-08-03' //occupata per la richiesta
.....
8 'c1' '2017-08-05' '2017-08-08' //libera per la richiesta
immettendo es. arrivo 2017-07-30 e partenza 2017-08-04 c1 risulta libera per cui dovuto aggiungere un controllo
quindi il tutto funziona
 

marino51

Utente Attivo
28 Feb 2013
2.912
162
63
Lombardia
@borgo italia
la tua soluzione non risolve il caso

arrivo 16 e partenza 19 deve risultare occupata (ev2 sovrapposto interno)
ev1 : 20170515 - 20170520 ev2 : 20170516 - 20170519
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.042
146
63
PR
www.borgo-italia.it
ciao
sei sicuro?
facendo varie prove
1) la camera risulta occupata se la data di arrivo OR partenza richiesta si interseca con le date in cui la camera è occupata
2) risulta occupata se il periodo richiesto si sovrappone perfettamente uguale
3) risulta occupata se il periodo richiesto eccede sia come arrivo che come partenza il periodo in cui la camera risulta gia occupata

questo è quello che ho in tabella
Codice:
1 'c1' '2017-08-01' '2017-08-03'
2 'c2' '2017-08-05' '2017-08-10'
3 'c3' '2017-08-01' '2017-08-08'
4 'c4' '2017-08-20' '2017-08-30'
5 'c5' '2017-08-12' '2017-08-25'
5 'c6' '2017-08-15' '2017-08-21'
6 'c1' '2017-08-05' '2017-08-08'
7 'c2' '2017-08-11' '2017-08-18'
e questi gli output (tralascio le libere che comunque risultano libere se non compaiono tra le occupate)
richiesta arrivo 2017-08-05 - partenza 2017-08-10
la camera c2 è occupata //periodo uguale al richiesto
la camera c3 è occupata //partenza interseca
la camera c1 è occupata //arrivo interseca
richiesta arrivo 2017-07-30 - partenza 2017-08-04
la camera c1 è occupata //si soprappone per eccedenza
la camera c3 è occupata //partenza interseca
 

marino51

Utente Attivo
28 Feb 2013
2.912
162
63
Lombardia
meglio scrivere un codice semplice ....
PHP:
$sql="SELECT count(*) FROM periodi WHERE data_fine >= ? AND ? >= data_inizio";
$borgo = $db->queryC( $sql, array( $ev2_inizio, $ev2_fine ) );
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.042
146
63
PR
www.borgo-italia.it
ciao @marino51
a parte la semplificazione (che a mio parere personale, la programmazione ad oggetti, non è una semplificazione), non capisco cosa tu intenda dove hai indicato la parte di script betven
PHP:
 WHERE
arrivo   BETWEEN '$arrivo' AND '$partenza'
OR
partenza BETWEEN '$arrivo' AND '$partenza'";

WHERE
20170515 BETWEEN 20170516 AND 20170519
OR
20170520 BETWEEN 20170516 AND 20170519
ho aggiunto una camera alla tabella coi dati che hai postato
Codice:
9 c8 2017-05-15 2017-05-20
e inserita la rihiesta $arrivo=2017-05-15 e $partenza=2017-05-19
cioè i dati che hai indicato e l'out è
richiesta arrivo 2017-05-15 - partenza 2017-05-19
la camera c8 è occupata

la camera c1 è libera
la camera c2 è libera
la camera c3 è libera
la camera c4 è libera
la camera c5 è libera
la camera c6 è libera
la camera c1 è libera
la camera c2 è libera
giustamente (con i dati che hai postato) la camera c8 risulta occupata

secondo me l'unica cosa eventualmente da aggiungere sulla query per le camere libere è GROUP BY camera e ORDER BY camera in quanto non importa sapere che le camere c1 e c2 sono libere anche in altri periodi (due o più record = due o più prenotazioni in periodi diversi) e in modo da averle ordinate
 

xone

Utente Attivo
4 Apr 2014
180
14
18
Salento
I due campi arrivo e partenza li ho creati in "date format" e l'unica query funzionante al 100% sembra che sia :
$sq1 = "SELECT * FROM booking WHERE NOT (partenza < '$date_in' OR '$date_out' < arrivo) AND pagamento = '1'";
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.042
146
63
PR
www.borgo-italia.it
ciao
io per fare prima ho usato il campo tipo stringa che comunque va bene con betwen e < o >, sempre confronto di stringe è.
non so cosa sia quel pagamento = '1'"; e tra l'altro non so come sia fatta esattamente la tabella, comunque il mio script l'ho testato con tutte le combinazioni possibili e funziona.
mentre per le camere 'ocupate' non c'è problema per le camere libere è leggermente diverso in quanto (mia supposizione) se la camera CN è prenotata/occupata dal 2017-08-05 al 2017-08-10 avrò un record con id= xy
se la stessa camera è occupata/prenotata anche dal 2017-09-10 al 2017-09-20 avrò un altro record con un id diverso e maggiore del precedente id=zw
ora se io faccio una richieta per la camera CN con
$arrivo 2017-08-06
$partenza 2017-08-20 (o qualsiasi altre date che vadano ad incidere/sovrapporsi con i valori del record xy)
non deve comunque risultarmi libera e la query per le camere libere mi estrae (causa record id=zw) risultando tra le libere per le date richieste
questo sempre che abbia ipotizzato giusto come è fatta la tabella.

alcune prove:
 

xone

Utente Attivo
4 Apr 2014
180
14
18
Salento
Ciao, pagamento = '1' è un sistema che sto implementando per far si che quando l'utente cerca una camera crea provvisoriamente un insert nel db con la prenotazione e pagamento = '0' poi se effettuatua il pagamento via paypal al ritorno se è andato a buon fine, si aggiorna la query settandosi su pagamento = '1' oppure se preme su annulla si elimina la query temporanea. In questo caso oltre a cercare le camere libere verifico pure che siano state pagate e confermate altrimenti risultano ancora libere. Non so se come sistema può andar bene è la prima volta che implemento questo tipo di script.