Come approccio questa query PHP / MYSQL?

1

Ho un sistema di prenotazione che ho codificato e il mio compito finale è quello di consentire all'utente di inserire un set di date e mostrarle tutte le opzioni disponibili.

La tabella delle prenotazioni è impostata con unit_id , check_in e check_out . Esistono dodici numeri di unità diversi.

Quindi devo in qualche modo scorrere attraverso di loro e trovare le unità che non hanno preso le date durante l'intervallo di date che l'utente ha inserito. Solo avendo qualche problema a concettualizzare cosa deve accadere.

Pseudo codice

$units = array (all the units);

foreach($units as $key = $value){

    Run a query searching through all reservations for that unit, 
    if the unit is available, add to our $available_units array for the view later

}

Controllare la disponibilità mi ha bloccato anche se. Qual è il modo più efficiente per utilizzare l'intervallo di date disponibile per i clienti e confrontare gli intervalli di date nel db?

    
posta absentx 28.04.2012 - 19:53
fonte

3 risposte

4

Mi imbatto in questo tipo di esigenza tutto il tempo. Supponiamo che tu abbia un intervallo di date che vuoi controllare (cioè trovare le unità libere per) che è definito con una data di inizio e una data di fine. Nel database, al fine di chiarire di cosa stiamo parlando, diciamo che le prenotazioni esistenti hanno una prima e una data ultima (della prenotazione).

Quindi ci sono sei possibili casi per ogni prenotazione (| xxxx |) rispetto all'intervallo di date che stai controllando ([----]):

  1. [--|xxxx|--] Può essere interamente contenuto all'interno del campo di controllo. Ciò significa che l'intervallo di date non è disponibile per questa unità.
  2. |xx[xx|----] Può cavalcare l'inizio dell'intervallo di controllo. Di nuovo, questa unità non è disponibile.
  3. [----|xx]xx| Può percorrere la fine dell'intervallo di controllo. Non disponibile.
  4. |xx[----]xx| Può contenere completamente il campo di controllo. Ancora, non disponibile.
  5. |xxxx|[----] Può precedere il campo di controllo. Questa unità potrebbe essere disponibile!
  6. [----]|xxxx| Può seguire interamente il campo di controllo. Questa unità potrebbe essere disponibile!

Noterai che in tutti i casi in cui l'unità non è disponibile, la prima data è sempre prima * la data di fine, e l'ultima data è sempre dopo * la data di inizio. Questo non è vero per i due casi in cui gli intervalli non si sovrappongono. Così! Abbiamo una condizione di distinzione.

(* o uguale a)

In questa situazione, le unità che sono in uso avranno almeno una prenotazione esistente dove first < = 'end' AND last > = 'start'. MySQL ha un sacco di funzioni di raggruppamento e aggregazione davvero belle che possiamo usare qui per ottenere effettivamente MySQL per fare tutto il lavoro pesante per noi. Ad esempio, potremmo fare qualcosa di simile:

SELECT Units.*, SUM(IF(ReservationID IS NULL, 0, First <= 'end' AND Last >= 'start')) AS ConflictingReservations
FROM Units LEFT JOIN Reservations USING (UnitID)
GROUP BY UnitID
HAVING ConflictingReservations = 0

Nella query precedente (che ammetto di non aver provato cough , ma l'idea è valida, onesta!) abbiamo lasciato unire la tabella Units alla tabella Reservations in modo che se un'unità non è mai stato prenotato, verrà comunque mostrato nei risultati. Da lì, raggruppiamo le righe per UnitID e creiamo una colonna derivata denominata "ConflictingReservations" che contiene la somma di un confronto logico. Come accennato in precedenza, se il confronto logico è VERO (che in MySQL ha il valore '1') significa che la specifica prenotazione che stiamo verificando si sovrappone all'intervallo di controllo. Sommando tutti gli "hit" ci forniremo il numero di prenotazioni per una particolare unità che si sovrappongono all'intervallo di controllo.

Nota: proteggiamo il confronto logico con il caso in cui un'unità non è mai stata prenotata prima e quindi il join sinistro restituisce una riga con valori NULL nella prima e nell'ultima colonna. Se ReservationID è NULL (e quindi la prima e l'ultima data saranno nulle, forzando l'intera colonna derivata da ConflictingReservations a NULL anziché a 0), la contiamo come non-match / false, ovvero: 0.

Il passo finale dice "butta via tutte le righe (cioè le unità) che hanno un numero diverso da zero di prenotazioni in conflitto". Questo dovrebbe lasciarti con un elenco di righe dalla tabella delle Unità che non hanno prenotazioni all'interno dell'intervallo di controllo (cioè, che sono disponibili per prenotare in quell'intervallo.)

Se sono riuscito a correggere i casi limite (come ho fatto con il caso zero prenotazioni) o la sintassi sbagliata, fammi sapere e modificherai la risposta!

    
risposta data 01.05.2012 - 12:18
fonte
1

Supponiamo che il cliente desideri che l'intervallo di date date_from sia date_to , dove date_from <= date_to . Ci hai detto che hai una tabella di prenotazione, chiamiamola reservation_table . Usando i nomi delle colonne che hai fornito, ovvero reservation_table = unit_id, check_in , check_out , tale che check_in <= check_out

Che ne dici della seguente query in mysql?

select r.unit_id from reservation_table r
  where r.check_in > date_to  OR r.check_out < date_from;
    
risposta data 29.04.2012 - 18:03
fonte
0

Ho costruito un sistema di prenotazione qualche tempo fa e ho affrontato un problema simile. Era leggermente diverso in quanto avevo un numero fisso di punti (unità) da riempire (non erano indicizzati).

La mia soluzione era simile alla risposta pubblicata da @rrufai, tranne che nel mio caso quella query mi avrebbe dato le prenotazioni per quell'intervallo di date, non la disponibilità.

Ho creato una funzione MySQL che eseguiva una query che recuperava il numero di prenotazioni per un dato giorno e restituiva quel numero. Da lì è stato sottratto dal numero di spot disponibili in totale, dandomi gli spot disponibili. Nel tuo caso, la tua funzione potrebbe restituire una lista di unità prese, quindi da quella capire quali sono libere (cioè non in quella lista).

L'ho ridotto a cercare al giorno (quindi avrei eseguito la funzione per n giorni che l'utente stava cercando, anche se immagino che tu possa fare il tutto in una singola funzione / procedura.

    
risposta data 30.04.2012 - 02:11
fonte

Leggi altre domande sui tag