Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL wählt Zeilen aus, in denen das Datum nicht zwischen dem Datum liegt

Angenommen, Sie sind daran interessiert, @Guests zu platzieren von @StartDate bis @EndDate

SELECT DISTINCT r.id, 
FROM room r 
     LEFT JOIN roombooking_room rbr ON r.id = rbr.room_id
     LEFT JOIN roombooking ON rbr.roombooking_id = rb.id
WHERE COALESCE(@StartDate NOT BETWEEN rb.startDate AND rb.endDate, TRUE)
      AND COALESCE(@EndDate NOT BETWEEN rb.startDate AND rb.endDate, TRUE)
      AND @Guests < r.maxGuests

sollte Ihnen eine Liste aller Zimmer geben, die frei sind und eine bestimmte Anzahl von Gästen für den angegebenen Zeitraum aufnehmen können.

HINWEISE
Diese Abfrage funktioniert nur für einzelne Räume, wenn Sie mehrere Räume betrachten möchten, müssen Sie dieselben Kriterien auf eine Kombination von Räumen anwenden. Dazu benötigen Sie rekursive Abfragen oder einige Hilfstabellen. COALESCE kümmert sich auch um NULLen - wenn ein Raum überhaupt nicht gebucht ist, hat er keine Datensätze mit Daten zum Vergleichen, sodass er nicht vollständig kostenlos zurückgegeben wird Räume. Das Datum zwischen Datum1 und Datum2 gibt NULL zurück, wenn entweder Datum1 oder Datum2 Null ist, und Coalesce setzt es auf True (Alternative ist eine UNION von vollständig freien Räumen; das könnte schneller sein).

Mit mehreren Räumen wird es wirklich interessant. Ist dieses Szenario ein großer Teil Ihres Problems? Und welche Datenbank verwenden Sie, d. h. haben Sie Zugriff auf rekursive Abfragen?

BEARBEITEN

Wie ich bereits mehrfach gesagt habe, ist Ihre Art, nach einer Lösung zu suchen (gieriger Algorithmus, der zuerst nach den größten freien Zimmern sucht), nicht optimal, wenn Sie die beste Übereinstimmung zwischen der erforderlichen Anzahl von Gästen und Zimmern erzielen möchten.

Wenn Sie also foreach durch

ersetzen
$bestCapacity = 0;
$bestSolution = array();

for ($i = 1; $i <= pow(2,sizeof($result))-1; $i++) {
    $solutionIdx = $i;
    $solutionGuests = 0;
    $solution = array();
    $j = 0;
    while ($solutionIdx > 0) :
        if ($solutionIdx % 2 == 1) {
            $solution[] = $result[$j]['id'];
            $solutionGuests += $result[$j]['maxGuests'];
        }
        $solutionIdx = intval($solutionIdx/2);
        $j++;
    endwhile;       
    if (($solutionGuests <= $bestCapacity || $bestCapacity == 0) && $solutionGuests >= $noGuests) {
        $bestCapacity = $solutionGuests;
        $bestSolution = $solution;
    }
}

print_r($bestSolution);
print_r($bestCapacity);

Wird alle möglichen Kombinationen durchgehen und finden Sie die Lösung, die die wenigsten Leerzeichen verschwendet.