Supondo que você esteja interessado em colocar
@Guests
de @StartDate
para @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
deve fornecer uma lista de todos os quartos que são gratuitos e podem acomodar um determinado número de hóspedes para o período determinado.
NOTAS
Esta consulta funciona apenas para quartos individuais, se você quiser ver vários quartos, precisará aplicar os mesmos critérios a uma combinação de quartos. Para isso, você precisaria de consultas recursivas ou algumas tabelas auxiliares. Além disso, o COALESCE está lá para cuidar dos NULLs - se um quarto não for reservado, ele não terá registros com datas para comparar, portanto, não retornará totalmente gratuito quartos. Date entre date1 e date2 retornará NULL se date1 ou date2 for nulo e coalesce o transformará em true (alternativa é fazer uma UNION de salas completamente livres; o que pode ser mais rápido).
Com várias salas, as coisas ficam realmente interessantes. Esse cenário é grande parte do seu problema? E qual banco de dados você está usando, ou seja, você tem acesso a consultas recursivas?
EDITAR
Como afirmei várias vezes antes, sua maneira de procurar uma solução (algoritmo ganancioso que analisa primeiro os maiores quartos gratuitos) não é a ideal se você deseja obter o melhor ajuste entre o número necessário de hóspedes e quartos.
Então, se você substituir seu foreach por
$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);
Passará por todas as combinações possíveis e encontre a solução que desperdiça o menor número de espaços.