Мне уже приходилось решать эту проблему ранее, и это забавно, но с тех пор я научился некоторым лучшим методам. В то время я полагаю, что создал процедуру или функцию для циклического выполнения запрошенных дат и возврата цены.
Чтобы вернуть необходимые строки, вы можете просто выбрать, используя верхний и нижний пределы. Вы можете указать дату в пределах критериев выбора, чтобы получить количество итераций для каждой из них.
Если все, что вы в конечном итоге ищете, это одна цена, я бы посоветовал объединить эту логику в функцию
Я предположил вторую таблицу, tbh_hotel с id (int PK == hotel_id) и default_charge (int) со строкой (id = 6, default_charge = 20)
Дальнейшие предположения заключаются в том, что когда ваши даты были "2010", вы подразумевали, что они были "2012", и что это для кого-то, кто регистрируется 15-го числа и выезжает 22-го (и поэтому нуждается в отеле для 15, 16, 17, 18, 19, 20, 21, 7 ночей). Я также предполагаю, что у вас есть логика, которая предотвращает перекрытие диапазонов дат, так что в tbl_charge нет двух строк, соответствующих дате 14 февраля 2012 (например)
Итак, чтобы начать это, запрос для выбора подходящих строк
SELECT
*
FROM tbl_charge AS c
WHERE
(
c.end_date >= '2012-02-15'
OR
c.start_date < '2012-02-22'
)
Это в значительной степени то, что у вас уже есть, поэтому теперь добавим еще несколько полей, чтобы получить информацию о том, на сколько дней применяется каждое правило.
SET @StartDate = '2012-02-15';
SET @EndDate = SUBDATE('2012-02-22',1);
SELECT
c.id,
c.start_date,
c.end_date,
c.charge_per_day,
DATEDIFF(IF(c.end_date>@EndDate,@EndDate,c.end_date),SUBDATE(IF(c.start_date<@StartDate,@StartDate,c.start_date),1)) AS quantityOfThisRate
FROM tbl_charge AS c
WHERE c.end_date >=@StartDate OR c.start_date < @EndDate
Я ПОДТВЕРЖДАЮ дату окончания, потому что, если вы выезжаете 22-го, ваша последняя дата регистрации 21-го. Я СУБДАТИРУЮ дату начала каждого DATEDIFF, потому что, если вы остаетесь 15 - 16 числа, субдата END DATE делает это 15-15 числами, и поэтому эта SUBDATE заставляет 14-15 числа возвращать правильное значение 1. Вывод теперь выглядит примерно так
id start_date end_date price quantityAtThisRate
1 2012-02-10 2012-02-15 20 1
2 2012-02-16 2012-02-18 30 3
3 2012-02-20 2012-02-29 50 2
Продолжая, я помещу это в подзапрос и объединю tbl_hotel, чтобы получить плату по умолчанию
SET @StartDate = '2012-02-15';
SET @EndDate = SUBDATE('2012-02-22',1);
SET @NumberOfNights = DATEDIFF(ADDDATE(@EndDate,1),@StartDate);
SET @HotelID = 6;
SELECT
SUM(specificDates.charge_per_day*specificDates.quantityAtThisRate) AS specificCharges,
@NumberOfNights-SUM(specificDates.quantityAtThisRate) AS daysAtDefault,
h.default_charge * (@NumberOfNights-SUM(specificDates.quantityAtThisRate)) AS defaultCharges
FROM tbl_hotel AS h
INNER JOIN
(
SELECT
c.charge_per_day,
DATEDIFF(IF(c.end_date>@EndDate,@EndDate,c.end_date),SUBDATE(IF(c.start_date<@StartDate,@StartDate,c.start_date),1)) AS quantityAtThisRate
FROM tbl_charge AS c
WHERE (c.end_date >=@StartDate OR c.start_date < @EndDate) AND c.hotel_id = @HotelID
) AS specificDates
WHERE h.id = @HotelID
Реально, один запрос получится довольно .... сложным, поэтому я остановлюсь на хранимой процедуре, опираясь на логику выше (как если бы не было особых правил, вышеприведенный запрос вернул бы ноль из-за внутреннего соединения)
Надеюсь, это поможет